##// END OF EJS Templates
Updated examples,...
Jonathan Frederic -
Show More
@@ -1,1045 +1,1022 b''
1 1 {
2 2 "metadata": {
3 3 "celltoolbar": "Slideshow",
4 4 "name": "",
5 5 "signature": "sha256:9763f005a69fc65b7a7977011d9604b09b4959e7293cbbb2cf35cc482380e671"
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 27 "outputs": [],
28 28 "prompt_number": 3
29 29 },
30 30 {
31 "cell_type": "code",
32 "collapsed": false,
33 "input": [
34 "%%html\n",
35 "<style>div.text_cell.cell.rendered.slideshow-slide { margin-top: 5em !important; }</style>"
36 ],
37 "language": "python",
38 "metadata": {},
39 "outputs": [
40 {
41 "html": [
42 "<style>div.text_cell.cell.rendered.slideshow-slide { margin-top: 5em !important; }</style>"
43 ],
44 "metadata": {},
45 "output_type": "display_data",
46 "text": [
47 "<IPython.core.display.HTML object>"
48 ]
49 }
50 ],
51 "prompt_number": 4
52 },
53 {
54 31 "cell_type": "heading",
55 32 "level": 1,
56 33 "metadata": {
57 34 "slideshow": {
58 35 "slide_type": "slide"
59 36 }
60 37 },
61 38 "source": [
62 39 "Building a Custom Widget"
63 40 ]
64 41 },
65 42 {
66 43 "cell_type": "markdown",
67 44 "metadata": {},
68 45 "source": [
69 46 "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",
70 47 "\n",
71 48 "** Insert framework layer image here. **\n",
72 49 "\n",
73 50 "To create a custom widget, you need to **define the widget both in the back-end and in the front-end**. "
74 51 ]
75 52 },
76 53 {
77 54 "cell_type": "heading",
78 55 "level": 1,
79 56 "metadata": {
80 57 "slideshow": {
81 58 "slide_type": "slide"
82 59 }
83 60 },
84 61 "source": [
85 62 "Building a Custom Widget"
86 63 ]
87 64 },
88 65 {
89 66 "cell_type": "markdown",
90 67 "metadata": {},
91 68 "source": [
92 69 "To get started, you'll create a **simple hello world widget**. Later you'll build on this foundation to make more complex widgets."
93 70 ]
94 71 },
95 72 {
96 73 "cell_type": "heading",
97 74 "level": 2,
98 75 "metadata": {
99 76 "slideshow": {
100 77 "slide_type": "slide"
101 78 }
102 79 },
103 80 "source": [
104 81 "Back-end (Python)"
105 82 ]
106 83 },
107 84 {
108 85 "cell_type": "heading",
109 86 "level": 3,
110 87 "metadata": {},
111 88 "source": [
112 89 "DOMWidget and Widget"
113 90 ]
114 91 },
115 92 {
116 93 "cell_type": "markdown",
117 94 "metadata": {},
118 95 "source": [
119 96 "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."
120 97 ]
121 98 },
122 99 {
123 100 "cell_type": "heading",
124 101 "level": 3,
125 102 "metadata": {
126 103 "slideshow": {
127 104 "slide_type": "slide"
128 105 }
129 106 },
130 107 "source": [
131 108 "_view_name"
132 109 ]
133 110 },
134 111 {
135 112 "cell_type": "markdown",
136 113 "metadata": {},
137 114 "source": [
138 115 "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)."
139 116 ]
140 117 },
141 118 {
142 119 "cell_type": "code",
143 120 "collapsed": false,
144 121 "input": [
145 122 "from IPython.html import widgets\n",
146 123 "from IPython.utils.traitlets import Unicode\n",
147 124 "\n",
148 125 "class HelloWidget(widgets.DOMWidget):\n",
149 126 " _view_name = Unicode('HelloView', sync=True)"
150 127 ],
151 128 "language": "python",
152 129 "metadata": {},
153 130 "outputs": [],
154 131 "prompt_number": 2
155 132 },
156 133 {
157 134 "cell_type": "heading",
158 135 "level": 3,
159 136 "metadata": {
160 137 "slideshow": {
161 138 "slide_type": "slide"
162 139 }
163 140 },
164 141 "source": [
165 142 "sync=True traitlets"
166 143 ]
167 144 },
168 145 {
169 146 "cell_type": "markdown",
170 147 "metadata": {},
171 148 "source": [
172 149 "**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`."
173 150 ]
174 151 },
175 152 {
176 153 "cell_type": "heading",
177 154 "level": 3,
178 155 "metadata": {
179 156 "slideshow": {
180 157 "slide_type": "slide"
181 158 }
182 159 },
183 160 "source": [
184 161 "Other traitlet types"
185 162 ]
186 163 },
187 164 {
188 165 "cell_type": "markdown",
189 166 "metadata": {},
190 167 "source": [
191 168 "Unicode, used for _view_name, is not the only Traitlet type, there are many more some of which are listed below: \n",
192 169 "\n",
193 170 "- Any\n",
194 171 "- Bool\n",
195 172 "- Bytes\n",
196 173 "- CBool\n",
197 174 "- CBytes\n",
198 175 "- CComplex\n",
199 176 "- CFloat\n",
200 177 "- CInt\n",
201 178 "- CLong\n",
202 179 "- CRegExp\n",
203 180 "- CUnicode\n",
204 181 "- CaselessStrEnum\n",
205 182 "- Complex\n",
206 183 "- Dict\n",
207 184 "- DottedObjectName\n",
208 185 "- Enum\n",
209 186 "- Float\n",
210 187 "- FunctionType\n",
211 188 "- Instance\n",
212 189 "- InstanceType\n",
213 190 "- Int\n",
214 191 "- List\n",
215 192 "- Long\n",
216 193 "- Set\n",
217 194 "- TCPAddress\n",
218 195 "- Tuple\n",
219 196 "- Type\n",
220 197 "- Unicode\n",
221 198 "\n",
222 199 "**Not all of these traitlets can be synchronized** across the network, **only the JSON-able** traits and **Widget instances** will be synchronized."
223 200 ]
224 201 },
225 202 {
226 203 "cell_type": "heading",
227 204 "level": 2,
228 205 "metadata": {
229 206 "slideshow": {
230 207 "slide_type": "slide"
231 208 }
232 209 },
233 210 "source": [
234 211 "Front-end (JavaScript)"
235 212 ]
236 213 },
237 214 {
238 215 "cell_type": "heading",
239 216 "level": 3,
240 217 "metadata": {},
241 218 "source": [
242 219 "Models and views"
243 220 ]
244 221 },
245 222 {
246 223 "cell_type": "markdown",
247 224 "metadata": {},
248 225 "source": [
249 226 "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**."
250 227 ]
251 228 },
252 229 {
253 230 "cell_type": "heading",
254 231 "level": 3,
255 232 "metadata": {
256 233 "slideshow": {
257 234 "slide_type": "slide"
258 235 }
259 236 },
260 237 "source": [
261 238 "Import the WidgetManager"
262 239 ]
263 240 },
264 241 {
265 242 "cell_type": "markdown",
266 243 "metadata": {},
267 244 "source": [
268 245 "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)."
269 246 ]
270 247 },
271 248 {
272 249 "cell_type": "code",
273 250 "collapsed": false,
274 251 "input": [
275 252 "%%javascript\n",
276 253 "\n",
277 254 "require([\"widgets/js/widget\"], function(WidgetManager){\n",
278 255 " \n",
279 256 "});"
280 257 ],
281 258 "language": "python",
282 259 "metadata": {},
283 260 "outputs": [
284 261 {
285 262 "javascript": [
286 263 "\n",
287 264 "require([\"widgets/js/widget\"], function(WidgetManager){\n",
288 265 " \n",
289 266 "});"
290 267 ],
291 268 "metadata": {},
292 269 "output_type": "display_data",
293 270 "text": [
294 271 "<IPython.core.display.Javascript object>"
295 272 ]
296 273 }
297 274 ],
298 275 "prompt_number": 3
299 276 },
300 277 {
301 278 "cell_type": "heading",
302 279 "level": 3,
303 280 "metadata": {
304 281 "slideshow": {
305 282 "slide_type": "slide"
306 283 }
307 284 },
308 285 "source": [
309 286 "Define the view"
310 287 ]
311 288 },
312 289 {
313 290 "cell_type": "markdown",
314 291 "metadata": {},
315 292 "source": [
316 293 "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**."
317 294 ]
318 295 },
319 296 {
320 297 "cell_type": "code",
321 298 "collapsed": false,
322 299 "input": [
323 300 "%%javascript\n",
324 301 "\n",
325 302 "require([\"widgets/js/widget\"], function(WidgetManager){\n",
326 303 " \n",
327 304 " // Define the HelloView\n",
328 305 " var HelloView = IPython.DOMWidgetView.extend({\n",
329 306 " \n",
330 307 " });\n",
331 308 " \n",
332 309 " // Register the HelloView with the widget manager.\n",
333 310 " WidgetManager.register_widget_view('HelloView', HelloView);\n",
334 311 "});"
335 312 ],
336 313 "language": "python",
337 314 "metadata": {},
338 315 "outputs": [
339 316 {
340 317 "javascript": [
341 318 "\n",
342 319 "require([\"widgets/js/widget\"], function(WidgetManager){\n",
343 320 " \n",
344 321 " // Define the HelloView\n",
345 322 " var HelloView = IPython.DOMWidgetView.extend({\n",
346 323 " \n",
347 324 " });\n",
348 325 " \n",
349 326 " // Register the HelloView with the widget manager.\n",
350 327 " WidgetManager.register_widget_view('HelloView', HelloView);\n",
351 328 "});"
352 329 ],
353 330 "metadata": {},
354 331 "output_type": "display_data",
355 332 "text": [
356 333 "<IPython.core.display.Javascript object>"
357 334 ]
358 335 }
359 336 ],
360 337 "prompt_number": 2
361 338 },
362 339 {
363 340 "cell_type": "heading",
364 341 "level": 3,
365 342 "metadata": {
366 343 "slideshow": {
367 344 "slide_type": "slide"
368 345 }
369 346 },
370 347 "source": [
371 348 "Render method"
372 349 ]
373 350 },
374 351 {
375 352 "cell_type": "markdown",
376 353 "metadata": {},
377 354 "source": [
378 355 "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)."
379 356 ]
380 357 },
381 358 {
382 359 "cell_type": "code",
383 360 "collapsed": false,
384 361 "input": [
385 362 "%%javascript\n",
386 363 "\n",
387 364 "require([\"widgets/js/widget\"], function(WidgetManager){ \n",
388 365 " \n",
389 366 " var HelloView = IPython.DOMWidgetView.extend({\n",
390 367 " \n",
391 368 " // Render the view.\n",
392 369 " render: function(){ \n",
393 370 " this.$el.text('Hello World!'); \n",
394 371 " },\n",
395 372 " });\n",
396 373 " \n",
397 374 " WidgetManager.register_widget_view('HelloView', HelloView);\n",
398 375 "});"
399 376 ],
400 377 "language": "python",
401 378 "metadata": {},
402 379 "outputs": [
403 380 {
404 381 "javascript": [
405 382 "\n",
406 383 "require([\"widgets/js/widget\"], function(WidgetManager){ \n",
407 384 " \n",
408 385 " var HelloView = IPython.DOMWidgetView.extend({\n",
409 386 " \n",
410 387 " // Render the view.\n",
411 388 " render: function(){ \n",
412 389 " this.$el.text('Hello World!'); \n",
413 390 " },\n",
414 391 " });\n",
415 392 " \n",
416 393 " WidgetManager.register_widget_view('HelloView', HelloView);\n",
417 394 "});"
418 395 ],
419 396 "metadata": {},
420 397 "output_type": "display_data",
421 398 "text": [
422 399 "<IPython.core.display.Javascript object>"
423 400 ]
424 401 }
425 402 ],
426 403 "prompt_number": 5
427 404 },
428 405 {
429 406 "cell_type": "heading",
430 407 "level": 2,
431 408 "metadata": {
432 409 "slideshow": {
433 410 "slide_type": "slide"
434 411 }
435 412 },
436 413 "source": [
437 414 "Test"
438 415 ]
439 416 },
440 417 {
441 418 "cell_type": "markdown",
442 419 "metadata": {},
443 420 "source": [
444 421 "You should be able to display your widget just like any other widget now."
445 422 ]
446 423 },
447 424 {
448 425 "cell_type": "code",
449 426 "collapsed": false,
450 427 "input": [
451 428 "HelloWidget()"
452 429 ],
453 430 "language": "python",
454 431 "metadata": {},
455 432 "outputs": [],
456 433 "prompt_number": 6
457 434 },
458 435 {
459 436 "cell_type": "heading",
460 437 "level": 2,
461 438 "metadata": {
462 439 "slideshow": {
463 440 "slide_type": "slide"
464 441 }
465 442 },
466 443 "source": [
467 444 "Making the widget stateful"
468 445 ]
469 446 },
470 447 {
471 448 "cell_type": "markdown",
472 449 "metadata": {},
473 450 "source": [
474 451 "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**."
475 452 ]
476 453 },
477 454 {
478 455 "cell_type": "code",
479 456 "collapsed": false,
480 457 "input": [
481 458 "class HelloWidget(widgets.DOMWidget):\n",
482 459 " _view_name = Unicode('HelloView', sync=True)\n",
483 460 " value = Unicode('Hello World!', sync=True)"
484 461 ],
485 462 "language": "python",
486 463 "metadata": {},
487 464 "outputs": [
488 465 {
489 466 "ename": "NameError",
490 467 "evalue": "name 'widgets' is not defined",
491 468 "output_type": "pyerr",
492 469 "traceback": [
493 470 "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
494 471 "\u001b[0;32m<ipython-input-5-18ff342e181d>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32mclass\u001b[0m \u001b[0mHelloWidget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mwidgets\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mDOMWidget\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0m_view_name\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mUnicode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'HelloView'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msync\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mvalue\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mUnicode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Hello World!'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msync\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
495 472 "\u001b[0;31mNameError\u001b[0m: name 'widgets' is not defined"
496 473 ]
497 474 }
498 475 ],
499 476 "prompt_number": 5
500 477 },
501 478 {
502 479 "cell_type": "heading",
503 480 "level": 3,
504 481 "metadata": {
505 482 "slideshow": {
506 483 "slide_type": "slide"
507 484 }
508 485 },
509 486 "source": [
510 487 "Accessing the model from the view"
511 488 ]
512 489 },
513 490 {
514 491 "cell_type": "markdown",
515 492 "metadata": {},
516 493 "source": [
517 494 "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)."
518 495 ]
519 496 },
520 497 {
521 498 "cell_type": "heading",
522 499 "level": 3,
523 500 "metadata": {
524 501 "slideshow": {
525 502 "slide_type": "slide"
526 503 }
527 504 },
528 505 "source": [
529 506 "Rendering model contents"
530 507 ]
531 508 },
532 509 {
533 510 "cell_type": "markdown",
534 511 "metadata": {},
535 512 "source": [
536 513 "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."
537 514 ]
538 515 },
539 516 {
540 517 "cell_type": "code",
541 518 "collapsed": false,
542 519 "input": [
543 520 "%%javascript\n",
544 521 "\n",
545 522 "require([\"widgets/js/widget\"], function(WidgetManager){ \n",
546 523 " \n",
547 524 " var HelloView = IPython.DOMWidgetView.extend({\n",
548 525 " \n",
549 526 " render: function(){ \n",
550 527 " this.$el.text(this.model.get('value')); \n",
551 528 " },\n",
552 529 " });\n",
553 530 " \n",
554 531 " WidgetManager.register_widget_view('HelloView', HelloView);\n",
555 532 "});"
556 533 ],
557 534 "language": "python",
558 535 "metadata": {},
559 536 "outputs": [
560 537 {
561 538 "javascript": [
562 539 "\n",
563 540 "require([\"widgets/js/widget\"], function(WidgetManager){ \n",
564 541 " \n",
565 542 " var HelloView = IPython.DOMWidgetView.extend({\n",
566 543 " \n",
567 544 " render: function(){ \n",
568 545 " this.$el.text(this.model.get('value')); \n",
569 546 " },\n",
570 547 " });\n",
571 548 " \n",
572 549 " WidgetManager.register_widget_view('HelloView', HelloView);\n",
573 550 "});"
574 551 ],
575 552 "metadata": {},
576 553 "output_type": "display_data",
577 554 "text": [
578 555 "<IPython.core.display.Javascript object>"
579 556 ]
580 557 }
581 558 ],
582 559 "prompt_number": 6
583 560 },
584 561 {
585 562 "cell_type": "heading",
586 563 "level": 3,
587 564 "metadata": {
588 565 "slideshow": {
589 566 "slide_type": "slide"
590 567 }
591 568 },
592 569 "source": [
593 570 "Dynamic updates"
594 571 ]
595 572 },
596 573 {
597 574 "cell_type": "markdown",
598 575 "metadata": {},
599 576 "source": [
600 577 "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)."
601 578 ]
602 579 },
603 580 {
604 581 "cell_type": "code",
605 582 "collapsed": false,
606 583 "input": [
607 584 "%%javascript\n",
608 585 "\n",
609 586 "require([\"widgets/js/widget\"], function(WidgetManager){ \n",
610 587 " \n",
611 588 " var HelloView = IPython.DOMWidgetView.extend({\n",
612 589 " \n",
613 590 " \n",
614 591 " render: function(){ \n",
615 592 " this.value_changed();\n",
616 593 " this.model.on('change:value', this.value_changed, this);\n",
617 594 " },\n",
618 595 " \n",
619 596 " value_changed: function() {\n",
620 597 " this.$el.text(this.model.get('value')); \n",
621 598 " },\n",
622 599 " });\n",
623 600 " \n",
624 601 " WidgetManager.register_widget_view('HelloView', HelloView);\n",
625 602 "});"
626 603 ],
627 604 "language": "python",
628 605 "metadata": {},
629 606 "outputs": [
630 607 {
631 608 "javascript": [
632 609 "\n",
633 610 "require([\"widgets/js/widget\"], function(WidgetManager){ \n",
634 611 " \n",
635 612 " var HelloView = IPython.DOMWidgetView.extend({\n",
636 613 " \n",
637 614 " \n",
638 615 " render: function(){ \n",
639 616 " this.value_changed();\n",
640 617 " this.model.on('change:value', this.value_changed, this);\n",
641 618 " },\n",
642 619 " \n",
643 620 " value_changed: function() {\n",
644 621 " this.$el.text(this.model.get('value')); \n",
645 622 " },\n",
646 623 " });\n",
647 624 " \n",
648 625 " WidgetManager.register_widget_view('HelloView', HelloView);\n",
649 626 "});"
650 627 ],
651 628 "metadata": {},
652 629 "output_type": "display_data",
653 630 "text": [
654 631 "<IPython.core.display.Javascript object>"
655 632 ]
656 633 }
657 634 ],
658 635 "prompt_number": 9
659 636 },
660 637 {
661 638 "cell_type": "heading",
662 639 "level": 2,
663 640 "metadata": {
664 641 "slideshow": {
665 642 "slide_type": "slide"
666 643 }
667 644 },
668 645 "source": [
669 646 "Test"
670 647 ]
671 648 },
672 649 {
673 650 "cell_type": "code",
674 651 "collapsed": false,
675 652 "input": [
676 653 "w = HelloWidget()\n",
677 654 "w"
678 655 ],
679 656 "language": "python",
680 657 "metadata": {},
681 658 "outputs": [],
682 659 "prompt_number": 10
683 660 },
684 661 {
685 662 "cell_type": "code",
686 663 "collapsed": false,
687 664 "input": [
688 665 "w.value = 'test'"
689 666 ],
690 667 "language": "python",
691 668 "metadata": {},
692 669 "outputs": [],
693 670 "prompt_number": 11
694 671 },
695 672 {
696 673 "cell_type": "heading",
697 674 "level": 1,
698 675 "metadata": {
699 676 "slideshow": {
700 677 "slide_type": "slide"
701 678 }
702 679 },
703 680 "source": [
704 681 "Finishing"
705 682 ]
706 683 },
707 684 {
708 685 "cell_type": "heading",
709 686 "level": 2,
710 687 "metadata": {},
711 688 "source": [
712 689 "Bidirectional communication"
713 690 ]
714 691 },
715 692 {
716 693 "cell_type": "markdown",
717 694 "metadata": {},
718 695 "source": [
719 696 "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."
720 697 ]
721 698 },
722 699 {
723 700 "cell_type": "heading",
724 701 "level": 3,
725 702 "metadata": {
726 703 "slideshow": {
727 704 "slide_type": "slide"
728 705 }
729 706 },
730 707 "source": [
731 708 "Update the Python code"
732 709 ]
733 710 },
734 711 {
735 712 "cell_type": "markdown",
736 713 "metadata": {},
737 714 "source": [
738 715 "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`."
739 716 ]
740 717 },
741 718 {
742 719 "cell_type": "code",
743 720 "collapsed": false,
744 721 "input": [
745 722 "from IPython.utils.traitlets import CInt\n",
746 723 "class SpinnerWidget(widgets.DOMWidget):\n",
747 724 " _view_name = Unicode('SpinnerView', sync=True)\n",
748 725 " value = CInt(0, sync=True)"
749 726 ],
750 727 "language": "python",
751 728 "metadata": {},
752 729 "outputs": [],
753 730 "prompt_number": 12
754 731 },
755 732 {
756 733 "cell_type": "heading",
757 734 "level": 3,
758 735 "metadata": {
759 736 "slideshow": {
760 737 "slide_type": "slide"
761 738 }
762 739 },
763 740 "source": [
764 741 "Updating the Javascript code"
765 742 ]
766 743 },
767 744 {
768 745 "cell_type": "markdown",
769 746 "metadata": {},
770 747 "source": [
771 748 "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."
772 749 ]
773 750 },
774 751 {
775 752 "cell_type": "code",
776 753 "collapsed": false,
777 754 "input": [
778 755 "%%javascript\n",
779 756 "\n",
780 757 "require([\"widgets/js/widget\"], function(WidgetManager){ \n",
781 758 " \n",
782 759 " var SpinnerView = IPython.DOMWidgetView.extend({\n",
783 760 " \n",
784 761 " render: function(){ \n",
785 762 " \n",
786 763 " // jQuery code to create a spinner and append it to $el\n",
787 764 " this.$input = $('<input />');\n",
788 765 " this.$el.append(this.$input);\n",
789 766 " this.$spinner = this.$input.spinner({\n",
790 767 " change: function( event, ui ) {}\n",
791 768 " });\n",
792 769 " \n",
793 770 " this.value_changed();\n",
794 771 " this.model.on('change:value', this.value_changed, this);\n",
795 772 " },\n",
796 773 " \n",
797 774 " value_changed: function() {\n",
798 775 " \n",
799 776 " },\n",
800 777 " });\n",
801 778 " \n",
802 779 " WidgetManager.register_widget_view('SpinnerView', SpinnerView);\n",
803 780 "});"
804 781 ],
805 782 "language": "python",
806 783 "metadata": {},
807 784 "outputs": [
808 785 {
809 786 "javascript": [
810 787 "\n",
811 788 "require([\"widgets/js/widget\"], function(WidgetManager){ \n",
812 789 " \n",
813 790 " var SpinnerView = IPython.DOMWidgetView.extend({\n",
814 791 " \n",
815 792 " render: function(){ \n",
816 793 " \n",
817 794 " // jQuery code to create a spinner and append it to $el\n",
818 795 " this.$input = $('<input />');\n",
819 796 " this.$el.append(this.$input);\n",
820 797 " this.$spinner = this.$input.spinner({\n",
821 798 " change: function( event, ui ) {}\n",
822 799 " });\n",
823 800 " \n",
824 801 " this.value_changed();\n",
825 802 " this.model.on('change:value', this.value_changed, this);\n",
826 803 " },\n",
827 804 " \n",
828 805 " value_changed: function() {\n",
829 806 " \n",
830 807 " },\n",
831 808 " });\n",
832 809 " \n",
833 810 " WidgetManager.register_widget_view('SpinnerView', SpinnerView);\n",
834 811 "});"
835 812 ],
836 813 "metadata": {},
837 814 "output_type": "display_data",
838 815 "text": [
839 816 "<IPython.core.display.Javascript object>"
840 817 ]
841 818 }
842 819 ],
843 820 "prompt_number": 13
844 821 },
845 822 {
846 823 "cell_type": "heading",
847 824 "level": 3,
848 825 "metadata": {
849 826 "slideshow": {
850 827 "slide_type": "slide"
851 828 }
852 829 },
853 830 "source": [
854 831 "Getting and setting the value"
855 832 ]
856 833 },
857 834 {
858 835 "cell_type": "markdown",
859 836 "metadata": {},
860 837 "source": [
861 838 "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.**"
862 839 ]
863 840 },
864 841 {
865 842 "cell_type": "code",
866 843 "collapsed": false,
867 844 "input": [
868 845 "%%javascript\n",
869 846 "\n",
870 847 "require([\"widgets/js/widget\"], function(WidgetManager){ \n",
871 848 " \n",
872 849 " var SpinnerView = IPython.DOMWidgetView.extend({\n",
873 850 " \n",
874 851 " render: function(){ \n",
875 852 "\n",
876 853 " var that = this;\n",
877 854 " this.$input = $('<input />');\n",
878 855 " this.$el.append(this.$input);\n",
879 856 " this.$spinner = this.$input.spinner({\n",
880 857 " change: function( event, ui ) {\n",
881 858 " that.handle_spin();\n",
882 859 " },\n",
883 860 " spin: function( event, ui ) {\n",
884 861 " that.handle_spin();\n",
885 862 " }\n",
886 863 " });\n",
887 864 " \n",
888 865 " this.value_changed();\n",
889 866 " this.model.on('change:value', this.value_changed, this);\n",
890 867 " },\n",
891 868 " \n",
892 869 " value_changed: function() {\n",
893 870 " this.$spinner.spinner('value', this.model.get('value'));\n",
894 871 " },\n",
895 872 " \n",
896 873 " handle_spin: function() {\n",
897 874 " this.model.set('value', this.$spinner.spinner('value'));\n",
898 875 " this.touch();\n",
899 876 " },\n",
900 877 " });\n",
901 878 " \n",
902 879 " WidgetManager.register_widget_view('SpinnerView', SpinnerView);\n",
903 880 "});"
904 881 ],
905 882 "language": "python",
906 883 "metadata": {},
907 884 "outputs": [
908 885 {
909 886 "javascript": [
910 887 "\n",
911 888 "require([\"widgets/js/widget\"], function(WidgetManager){ \n",
912 889 " \n",
913 890 " var SpinnerView = IPython.DOMWidgetView.extend({\n",
914 891 " \n",
915 892 " render: function(){ \n",
916 893 "\n",
917 894 " var that = this;\n",
918 895 " this.$input = $('<input />');\n",
919 896 " this.$el.append(this.$input);\n",
920 897 " this.$spinner = this.$input.spinner({\n",
921 898 " change: function( event, ui ) {\n",
922 899 " that.handle_spin();\n",
923 900 " },\n",
924 901 " spin: function( event, ui ) {\n",
925 902 " that.handle_spin();\n",
926 903 " }\n",
927 904 " });\n",
928 905 " \n",
929 906 " this.value_changed();\n",
930 907 " this.model.on('change:value', this.value_changed, this);\n",
931 908 " },\n",
932 909 " \n",
933 910 " value_changed: function() {\n",
934 911 " this.$spinner.spinner('value', this.model.get('value'));\n",
935 912 " },\n",
936 913 " \n",
937 914 " handle_spin: function() {\n",
938 915 " this.model.set('value', this.$spinner.spinner('value'));\n",
939 916 " this.touch();\n",
940 917 " },\n",
941 918 " });\n",
942 919 " \n",
943 920 " WidgetManager.register_widget_view('SpinnerView', SpinnerView);\n",
944 921 "});"
945 922 ],
946 923 "metadata": {},
947 924 "output_type": "display_data",
948 925 "text": [
949 926 "<IPython.core.display.Javascript object>"
950 927 ]
951 928 }
952 929 ],
953 930 "prompt_number": 14
954 931 },
955 932 {
956 933 "cell_type": "heading",
957 934 "level": 2,
958 935 "metadata": {
959 936 "slideshow": {
960 937 "slide_type": "slide"
961 938 }
962 939 },
963 940 "source": [
964 941 "Test"
965 942 ]
966 943 },
967 944 {
968 945 "cell_type": "code",
969 946 "collapsed": false,
970 947 "input": [
971 948 "w = SpinnerWidget(value=5)\n",
972 949 "w"
973 950 ],
974 951 "language": "python",
975 952 "metadata": {},
976 953 "outputs": [],
977 954 "prompt_number": 15
978 955 },
979 956 {
980 957 "cell_type": "code",
981 958 "collapsed": false,
982 959 "input": [
983 960 "w.value"
984 961 ],
985 962 "language": "python",
986 963 "metadata": {},
987 964 "outputs": [
988 965 {
989 966 "metadata": {},
990 967 "output_type": "pyout",
991 968 "prompt_number": 16,
992 969 "text": [
993 970 "5"
994 971 ]
995 972 }
996 973 ],
997 974 "prompt_number": 16
998 975 },
999 976 {
1000 977 "cell_type": "code",
1001 978 "collapsed": false,
1002 979 "input": [
1003 980 "w.value = 20"
1004 981 ],
1005 982 "language": "python",
1006 983 "metadata": {},
1007 984 "outputs": [],
1008 985 "prompt_number": 17
1009 986 },
1010 987 {
1011 988 "cell_type": "markdown",
1012 989 "metadata": {},
1013 990 "source": [
1014 991 "Trying to **use the spinner with another widget**."
1015 992 ]
1016 993 },
1017 994 {
1018 995 "cell_type": "code",
1019 996 "collapsed": false,
1020 997 "input": [
1021 998 "from IPython.display import display\n",
1022 999 "w1 = SpinnerWidget(value=0)\n",
1023 1000 "w2 = widgets.IntSliderWidget()\n",
1024 1001 "display(w1,w2)\n",
1025 1002 "\n",
1026 1003 "from IPython.utils.traitlets import link\n",
1027 1004 "mylink = link((w1, 'value'), (w2, 'value'))"
1028 1005 ],
1029 1006 "language": "python",
1030 1007 "metadata": {},
1031 1008 "outputs": [],
1032 1009 "prompt_number": 18
1033 1010 },
1034 1011 {
1035 1012 "cell_type": "markdown",
1036 1013 "metadata": {},
1037 1014 "source": [
1038 1015 "[Index](Index.ipynb) - [Back](Widget Styling.ipynb)"
1039 1016 ]
1040 1017 }
1041 1018 ],
1042 1019 "metadata": {}
1043 1020 }
1044 1021 ]
1045 1022 } No newline at end of file
@@ -1,417 +1,456 b''
1 1 {
2 2 "metadata": {
3 3 "celltoolbar": "Slideshow",
4 4 "name": "",
5 "signature": "sha256:7a953d1eb1417e7212ddeb70602b36355521ca1907ac33b089850ccea35bd8ab"
5 "signature": "sha256:f6c1dd624d35ab0c768f77dffdae914baf4d88a3c244047c00ffca8b9c96e81e"
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 "cell_type": "code",
21 "collapsed": false,
22 "input": [
23 "%%html\n",
24 "<style>div.text_cell.cell.rendered.slideshow-slide { margin-top: 5em !important; }</style>"
25 ],
26 "language": "python",
20 "cell_type": "heading",
21 "level": 1,
27 22 "metadata": {},
28 "outputs": [
29 {
30 "html": [
31 "<style>div.text_cell.cell.rendered.slideshow-slide { margin-top: 5em !important; }</style>"
32 ],
33 "metadata": {},
34 "output_type": "display_data",
35 "text": [
36 "<IPython.core.display.HTML object>"
37 ]
38 }
39 ],
40 "prompt_number": 11
23 "source": [
24 "Simple Widget Introduction"
25 ]
26 },
27 {
28 "cell_type": "heading",
29 "level": 2,
30 "metadata": {},
31 "source": [
32 "What are widgets?"
33 ]
41 34 },
42 35 {
43 36 "cell_type": "markdown",
44 37 "metadata": {
45 38 "slideshow": {
46 39 "slide_type": "slide"
47 40 }
48 41 },
49 42 "source": [
50 "# Simple Widget Introduction\n",
51 "\n",
52 "## What are widgets?\n",
53 43 "Widgets are elements that exists in both the front-end and the back-end.\n",
54 44 "\n",
55 45 "** Insert Frontend-Backend Picture **"
56 46 ]
57 47 },
58 48 {
49 "cell_type": "heading",
50 "level": 2,
51 "metadata": {},
52 "source": [
53 "What can they be used for?"
54 ]
55 },
56 {
59 57 "cell_type": "markdown",
60 58 "metadata": {
61 59 "slideshow": {
62 60 "slide_type": "slide"
63 61 }
64 62 },
65 63 "source": [
66 "## What can they be used for?\n",
67 64 "You can use widgets to build **interactive GUIs** for your notebooks. \n",
68 65 "You can also use widgets to **synchronize stateful and stateless information** between Python and JavaScript."
69 66 ]
70 67 },
71 68 {
69 "cell_type": "heading",
70 "level": 2,
71 "metadata": {},
72 "source": [
73 "Using widgets "
74 ]
75 },
76 {
72 77 "cell_type": "markdown",
73 78 "metadata": {
74 79 "slideshow": {
75 80 "slide_type": "slide"
76 81 }
77 82 },
78 83 "source": [
79 "## Using widgets \n",
80 84 "To use the widget framework, you need to **import `IPython.html.widgets`**."
81 85 ]
82 86 },
83 87 {
84 88 "cell_type": "code",
85 89 "collapsed": false,
86 90 "input": [
87 91 "from IPython.html.widgets import *"
88 92 ],
89 93 "language": "python",
90 94 "metadata": {},
91 95 "outputs": [],
92 96 "prompt_number": 1
93 97 },
94 98 {
95 99 "cell_type": "heading",
96 100 "level": 3,
97 101 "metadata": {
98 102 "slideshow": {
99 103 "slide_type": "slide"
100 104 }
101 105 },
102 106 "source": [
103 107 "repr"
104 108 ]
105 109 },
106 110 {
107 111 "cell_type": "markdown",
108 112 "metadata": {},
109 113 "source": [
110 114 "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."
111 115 ]
112 116 },
113 117 {
114 118 "cell_type": "code",
115 119 "collapsed": false,
116 120 "input": [
117 121 "IntSliderWidget()"
118 122 ],
119 123 "language": "python",
120 124 "metadata": {},
121 125 "outputs": [],
122 126 "prompt_number": 2
123 127 },
124 128 {
125 129 "cell_type": "heading",
126 130 "level": 3,
127 131 "metadata": {
128 132 "slideshow": {
129 133 "slide_type": "slide"
130 134 }
131 135 },
132 136 "source": [
133 137 "display()"
134 138 ]
135 139 },
136 140 {
137 141 "cell_type": "markdown",
138 142 "metadata": {},
139 143 "source": [
140 144 "You can also explicitly display the widget using `display(...)`."
141 145 ]
142 146 },
143 147 {
144 148 "cell_type": "code",
145 149 "collapsed": false,
146 150 "input": [
147 151 "from IPython.display import display\n",
148 152 "w = IntSliderWidget()\n",
149 153 "display(w)"
150 154 ],
151 155 "language": "python",
152 156 "metadata": {},
153 157 "outputs": [],
154 158 "prompt_number": 3
155 159 },
156 160 {
157 161 "cell_type": "heading",
158 162 "level": 3,
159 163 "metadata": {
160 164 "slideshow": {
161 165 "slide_type": "slide"
162 166 }
163 167 },
164 168 "source": [
165 169 "Multiple display() calls"
166 170 ]
167 171 },
168 172 {
169 173 "cell_type": "markdown",
170 174 "metadata": {},
171 175 "source": [
172 176 "If you display the same widget twice, the displayed instances in the front-end **will remain in sync** with each other."
173 177 ]
174 178 },
175 179 {
176 180 "cell_type": "code",
177 181 "collapsed": false,
178 182 "input": [
179 183 "display(w)"
180 184 ],
181 185 "language": "python",
182 186 "metadata": {},
183 187 "outputs": [],
184 188 "prompt_number": 4
185 189 },
186 190 {
191 "cell_type": "heading",
192 "level": 2,
193 "metadata": {},
194 "source": [
195 "Why does displaying the same widget twice work?"
196 ]
197 },
198 {
187 199 "cell_type": "markdown",
188 200 "metadata": {
189 201 "slideshow": {
190 202 "slide_type": "slide"
191 203 }
192 204 },
193 205 "source": [
194 "## Why does displaying the same widget twice work?\n",
195 206 "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",
196 207 "\n",
197 208 "** Insert Backend-Frontend Views Figure **"
198 209 ]
199 210 },
200 211 {
201 212 "cell_type": "heading",
202 213 "level": 3,
203 214 "metadata": {
204 215 "slideshow": {
205 216 "slide_type": "slide"
206 217 }
207 218 },
208 219 "source": [
209 220 "Closing widgets"
210 221 ]
211 222 },
212 223 {
213 224 "cell_type": "markdown",
214 225 "metadata": {},
215 226 "source": [
216 227 "You can close a widget by calling its `close()` method."
217 228 ]
218 229 },
219 230 {
220 231 "cell_type": "code",
221 232 "collapsed": false,
222 233 "input": [
223 234 "w.close()"
224 235 ],
225 236 "language": "python",
226 237 "metadata": {},
227 238 "outputs": [],
228 239 "prompt_number": 5
229 240 },
230 241 {
242 "cell_type": "heading",
243 "level": 2,
244 "metadata": {},
245 "source": [
246 "Widget properties"
247 ]
248 },
249 {
231 250 "cell_type": "markdown",
232 251 "metadata": {
233 252 "slideshow": {
234 253 "slide_type": "slide"
235 254 }
236 255 },
237 256 "source": [
238 "## Widget properties\n",
239 257 "All of the IPython widgets **share a similar naming scheme**. To read the value of a widget, you can query its `value` property."
240 258 ]
241 259 },
242 260 {
243 261 "cell_type": "code",
244 262 "collapsed": false,
245 263 "input": [
246 264 "w.value"
247 265 ],
248 266 "language": "python",
249 267 "metadata": {},
250 268 "outputs": [
251 269 {
252 270 "metadata": {},
253 271 "output_type": "pyout",
254 272 "prompt_number": 6,
255 273 "text": [
256 274 "0"
257 275 ]
258 276 }
259 277 ],
260 278 "prompt_number": 6
261 279 },
262 280 {
263 281 "cell_type": "markdown",
264 282 "metadata": {},
265 283 "source": [
266 284 "Similarly, to set a widget's value, you can set its `value` property."
267 285 ]
268 286 },
269 287 {
270 288 "cell_type": "code",
271 289 "collapsed": false,
272 290 "input": [
273 291 "w.value = 100"
274 292 ],
275 293 "language": "python",
276 294 "metadata": {},
277 295 "outputs": [],
278 296 "prompt_number": 7
279 297 },
280 298 {
281 299 "cell_type": "heading",
282 300 "level": 3,
283 301 "metadata": {
284 302 "slideshow": {
285 303 "slide_type": "slide"
286 304 }
287 305 },
288 306 "source": [
289 307 "Keys"
290 308 ]
291 309 },
292 310 {
293 311 "cell_type": "markdown",
294 312 "metadata": {},
295 313 "source": [
296 314 "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**."
297 315 ]
298 316 },
299 317 {
300 318 "cell_type": "code",
301 319 "collapsed": false,
302 320 "input": [
303 321 "w.keys"
304 322 ],
305 323 "language": "python",
306 324 "metadata": {},
307 325 "outputs": [
308 326 {
309 327 "metadata": {},
310 328 "output_type": "pyout",
311 329 "prompt_number": 8,
312 330 "text": [
313 331 "['_view_name',\n",
314 332 " 'orientation',\n",
315 333 " 'msg_throttle',\n",
316 334 " 'min',\n",
317 335 " 'max',\n",
318 336 " '_css',\n",
319 337 " 'value',\n",
320 338 " 'readout',\n",
321 339 " 'disabled',\n",
322 340 " 'visible',\n",
323 341 " 'step',\n",
324 342 " 'description']"
325 343 ]
326 344 }
327 345 ],
328 346 "prompt_number": 8
329 347 },
330 348 {
349 "cell_type": "heading",
350 "level": 3,
351 "metadata": {},
352 "source": [
353 "Shorthand for setting the initial values of widget properties"
354 ]
355 },
356 {
331 357 "cell_type": "markdown",
332 358 "metadata": {
333 359 "slideshow": {
334 360 "slide_type": "slide"
335 361 }
336 362 },
337 363 "source": [
338 "### Shorthand for setting the initial values of widget properties\n",
339 364 "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)."
340 365 ]
341 366 },
342 367 {
343 368 "cell_type": "code",
344 369 "collapsed": false,
345 370 "input": [
346 371 "TextWidget(value='Hello World!', disabled=True)"
347 372 ],
348 373 "language": "python",
349 374 "metadata": {},
350 375 "outputs": [],
351 376 "prompt_number": 9
352 377 },
353 378 {
379 "cell_type": "heading",
380 "level": 2,
381 "metadata": {},
382 "source": [
383 "Linking two similar widgets"
384 ]
385 },
386 {
354 387 "cell_type": "markdown",
355 388 "metadata": {
356 389 "slideshow": {
357 390 "slide_type": "slide"
358 391 }
359 392 },
360 393 "source": [
361 "## Linking two similar widgets\n",
362 394 "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."
363 395 ]
364 396 },
365 397 {
366 398 "cell_type": "code",
367 399 "collapsed": false,
368 400 "input": [
369 401 "from IPython.utils.traitlets import link\n",
370 402 "a = FloatTextWidget()\n",
371 403 "b = FloatSliderWidget()\n",
372 404 "c = FloatProgressWidget()\n",
373 405 "display(a,b,c)\n",
374 406 "\n",
375 407 "\n",
376 408 "mylink = link((a, 'value'), (b, 'value'), (c, 'value'))"
377 409 ],
378 410 "language": "python",
379 411 "metadata": {},
380 412 "outputs": [],
381 413 "prompt_number": 10
382 414 },
383 415 {
416 "cell_type": "heading",
417 "level": 3,
418 "metadata": {},
419 "source": [
420 "Unlinking widgets"
421 ]
422 },
423 {
384 424 "cell_type": "markdown",
385 425 "metadata": {
386 426 "slideshow": {
387 427 "slide_type": "slide"
388 428 }
389 429 },
390 430 "source": [
391 "### Unlinking widgets\n",
392 431 "Unlinking the widgets is simple. All you have to do is call `.unlink` on the link object."
393 432 ]
394 433 },
395 434 {
396 435 "cell_type": "code",
397 436 "collapsed": false,
398 437 "input": [
399 438 "mylink.unlink()"
400 439 ],
401 440 "language": "python",
402 441 "metadata": {},
403 442 "outputs": [],
404 443 "prompt_number": 11
405 444 },
406 445 {
407 446 "cell_type": "markdown",
408 447 "metadata": {},
409 448 "source": [
410 449 "[Index](Index.ipynb) - [Next](Widget List.ipynb)"
411 450 ]
412 451 }
413 452 ],
414 453 "metadata": {}
415 454 }
416 455 ]
417 456 } No newline at end of file
@@ -1,302 +1,279 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:9f69a28be85dccdcc7e2b5d742047aa140a572d19e4215467aa88745c29ffce7"
11 "signature": "sha256:ac1b90929c7736b2261ba498b6f28dd89d3e7b7981c43f937879febe6841e4cd"
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 "cell_type": "code",
27 "collapsed": false,
28 "input": [
29 "%%html\n",
30 "<style>div.text_cell.cell.rendered.slideshow-slide { margin-top: 5em !important; }</style>"
31 ],
32 "language": "python",
33 "metadata": {},
34 "outputs": [
35 {
36 "html": [
37 "<style>div.text_cell.cell.rendered.slideshow-slide { margin-top: 5em !important; }</style>"
38 ],
39 "metadata": {},
40 "output_type": "display_data",
41 "text": [
42 "<IPython.core.display.HTML object>"
43 ]
44 }
45 ],
46 "prompt_number": 1
47 },
48 {
49 26 "cell_type": "heading",
50 27 "level": 1,
51 28 "metadata": {
52 29 "slideshow": {
53 30 "slide_type": "slide"
54 31 }
55 32 },
56 33 "source": [
57 34 "Widget Events"
58 35 ]
59 36 },
60 37 {
61 38 "cell_type": "heading",
62 39 "level": 2,
63 40 "metadata": {},
64 41 "source": [
65 42 "Special events"
66 43 ]
67 44 },
68 45 {
69 46 "cell_type": "code",
70 47 "collapsed": false,
71 48 "input": [
72 49 "from __future__ import print_function"
73 50 ],
74 51 "language": "python",
75 52 "metadata": {},
76 53 "outputs": [],
77 54 "prompt_number": 1
78 55 },
79 56 {
80 57 "cell_type": "markdown",
81 58 "metadata": {},
82 59 "source": [
83 60 "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."
84 61 ]
85 62 },
86 63 {
87 64 "cell_type": "code",
88 65 "collapsed": false,
89 66 "input": [
90 67 "from IPython.html import widgets\n",
91 68 "print(widgets.ButtonWidget.on_click.__doc__)"
92 69 ],
93 70 "language": "python",
94 71 "metadata": {},
95 72 "outputs": [
96 73 {
97 74 "output_type": "stream",
98 75 "stream": "stdout",
99 76 "text": [
100 77 "Register a callback to execute when the button is clicked.\n",
101 78 "\n",
102 79 " The callback will be called with one argument,\n",
103 80 " the clicked button widget instance.\n",
104 81 "\n",
105 82 " Parameters\n",
106 83 " ----------\n",
107 84 " remove : bool (optional)\n",
108 85 " Set to true to remove the callback from the list of callbacks.\n"
109 86 ]
110 87 }
111 88 ],
112 89 "prompt_number": 2
113 90 },
114 91 {
115 92 "cell_type": "heading",
116 93 "level": 3,
117 94 "metadata": {
118 95 "slideshow": {
119 96 "slide_type": "slide"
120 97 }
121 98 },
122 99 "source": [
123 100 "Example"
124 101 ]
125 102 },
126 103 {
127 104 "cell_type": "markdown",
128 105 "metadata": {},
129 106 "source": [
130 107 "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."
131 108 ]
132 109 },
133 110 {
134 111 "cell_type": "code",
135 112 "collapsed": false,
136 113 "input": [
137 114 "from IPython.display import display\n",
138 115 "button = widgets.ButtonWidget(description=\"Click Me!\")\n",
139 116 "display(button)\n",
140 117 "\n",
141 118 "def on_button_clicked(b):\n",
142 119 " print(\"Button clicked.\")\n",
143 120 "\n",
144 121 "button.on_click(on_button_clicked)"
145 122 ],
146 123 "language": "python",
147 124 "metadata": {},
148 125 "outputs": [],
149 126 "prompt_number": 3
150 127 },
151 128 {
152 129 "cell_type": "heading",
153 130 "level": 3,
154 131 "metadata": {
155 132 "slideshow": {
156 133 "slide_type": "slide"
157 134 }
158 135 },
159 136 "source": [
160 137 "on_sumbit"
161 138 ]
162 139 },
163 140 {
164 141 "cell_type": "markdown",
165 142 "metadata": {},
166 143 "source": [
167 144 "The **`TextWidget`** also has a special **`on_submit` event**. The `on_submit` event **fires when the user hits return**."
168 145 ]
169 146 },
170 147 {
171 148 "cell_type": "code",
172 149 "collapsed": false,
173 150 "input": [
174 151 "text = widgets.TextWidget()\n",
175 152 "display(text)\n",
176 153 "\n",
177 154 "def handle_submit(sender):\n",
178 155 " print(text.value)\n",
179 156 "\n",
180 157 "text.on_submit(handle_submit)"
181 158 ],
182 159 "language": "python",
183 160 "metadata": {},
184 161 "outputs": [],
185 162 "prompt_number": 4
186 163 },
187 164 {
188 165 "cell_type": "heading",
189 166 "level": 2,
190 167 "metadata": {
191 168 "slideshow": {
192 169 "slide_type": "slide"
193 170 }
194 171 },
195 172 "source": [
196 173 "Traitlet events"
197 174 ]
198 175 },
199 176 {
200 177 "cell_type": "markdown",
201 178 "metadata": {},
202 179 "source": [
203 180 "**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."
204 181 ]
205 182 },
206 183 {
207 184 "cell_type": "code",
208 185 "collapsed": false,
209 186 "input": [
210 187 "print(widgets.Widget.on_trait_change.__doc__)"
211 188 ],
212 189 "language": "python",
213 190 "metadata": {},
214 191 "outputs": [
215 192 {
216 193 "output_type": "stream",
217 194 "stream": "stdout",
218 195 "text": [
219 196 "Setup a handler to be called when a trait changes.\n",
220 197 "\n",
221 198 " This is used to setup dynamic notifications of trait changes.\n",
222 199 "\n",
223 200 " Static handlers can be created by creating methods on a HasTraits\n",
224 201 " subclass with the naming convention '_[traitname]_changed'. Thus,\n",
225 202 " to create static handler for the trait 'a', create the method\n",
226 203 " _a_changed(self, name, old, new) (fewer arguments can be used, see\n",
227 204 " below).\n",
228 205 "\n",
229 206 " Parameters\n",
230 207 " ----------\n",
231 208 " handler : callable\n",
232 209 " A callable that is called when a trait changes. Its\n",
233 210 " signature can be handler(), handler(name), handler(name, new)\n",
234 211 " or handler(name, old, new).\n",
235 212 " name : list, str, None\n",
236 213 " If None, the handler will apply to all traits. If a list\n",
237 214 " of str, handler will apply to all names in the list. If a\n",
238 215 " str, the handler will apply just to that name.\n",
239 216 " remove : bool\n",
240 217 " If False (the default), then install the handler. If True\n",
241 218 " then unintall it.\n",
242 219 " \n"
243 220 ]
244 221 }
245 222 ],
246 223 "prompt_number": 5
247 224 },
248 225 {
249 226 "cell_type": "heading",
250 227 "level": 3,
251 228 "metadata": {
252 229 "slideshow": {
253 230 "slide_type": "slide"
254 231 }
255 232 },
256 233 "source": [
257 234 "Signatures"
258 235 ]
259 236 },
260 237 {
261 238 "cell_type": "markdown",
262 239 "metadata": {},
263 240 "source": [
264 241 "Mentioned in the doc string, the callback registered can have **4 possible signatures**:\n",
265 242 "\n",
266 243 "- callback()\n",
267 244 "- callback(trait_name)\n",
268 245 "- callback(trait_name, new_value)\n",
269 246 "- callback(trait_name, old_value, new_value)\n",
270 247 "\n",
271 248 "Using this method, an example of how to output an IntSliderWiget's value as it is changed can be seen below."
272 249 ]
273 250 },
274 251 {
275 252 "cell_type": "code",
276 253 "collapsed": false,
277 254 "input": [
278 255 "int_range = widgets.IntSliderWidget()\n",
279 256 "display(int_range)\n",
280 257 "\n",
281 258 "def on_value_change(name, value):\n",
282 259 " print(value)\n",
283 260 "\n",
284 261 "int_range.on_trait_change(on_value_change, 'value')"
285 262 ],
286 263 "language": "python",
287 264 "metadata": {},
288 265 "outputs": [],
289 266 "prompt_number": 6
290 267 },
291 268 {
292 269 "cell_type": "markdown",
293 270 "metadata": {},
294 271 "source": [
295 272 "[Index](Index.ipynb) - [Back](Widget List.ipynb) - [Next](Widget Styling.ipynb)"
296 273 ]
297 274 }
298 275 ],
299 276 "metadata": {}
300 277 }
301 278 ]
302 279 } No newline at end of file
@@ -1,661 +1,651 b''
1 1 {
2 2 "metadata": {
3 3 "celltoolbar": "Slideshow",
4 4 "name": "",
5 "signature": "sha256:e6f77565893357e0302d40f80fbb389950912ab04a07b64026e28720cf11bfbe"
5 "signature": "sha256:4200cc7b2c7067f4c5391eeee6ba0d9be43b4faa16a245ba1634e7de66150372"
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 "cell_type": "code",
21 "collapsed": false,
22 "input": [
23 "%%html\n",
24 "<style>div.text_cell.cell.rendered.slideshow-slide { margin-top: 5em !important; }</style>"
25 ],
26 "language": "python",
20 "cell_type": "heading",
21 "level": 1,
27 22 "metadata": {},
28 "outputs": [
29 {
30 "html": [
31 "<style>div.text_cell.cell.rendered.slideshow-slide { margin-top: 5em !important; }</style>"
32 ],
33 "metadata": {},
34 "output_type": "display_data",
35 "text": [
36 "<IPython.core.display.HTML object>"
37 ]
38 }
39 ],
40 "prompt_number": 1
23 "source": [
24 "Widget List"
25 ]
26 },
27 {
28 "cell_type": "heading",
29 "level": 2,
30 "metadata": {},
31 "source": [
32 "Complete list"
33 ]
41 34 },
42 35 {
43 36 "cell_type": "markdown",
44 37 "metadata": {
45 38 "slideshow": {
46 39 "slide_type": "slide"
47 40 }
48 41 },
49 42 "source": [
50 "# Widget List\n",
51 "\n",
52 "## Complete list\n",
53 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."
54 44 ]
55 45 },
56 46 {
57 47 "cell_type": "code",
58 48 "collapsed": false,
59 49 "input": [
60 50 "from IPython.html import widgets\n",
61 51 "[w for w in dir(widgets) if w.endswith('Widget')]"
62 52 ],
63 53 "language": "python",
64 54 "metadata": {},
65 55 "outputs": [
66 56 {
67 57 "metadata": {},
68 58 "output_type": "pyout",
69 59 "prompt_number": 1,
70 60 "text": [
71 61 "['AccordionWidget',\n",
72 62 " 'BoundedFloatTextWidget',\n",
73 63 " 'BoundedIntTextWidget',\n",
74 64 " 'ButtonWidget',\n",
75 65 " 'CheckboxWidget',\n",
76 66 " 'ContainerWidget',\n",
77 67 " 'DOMWidget',\n",
78 68 " 'DropdownWidget',\n",
79 69 " 'FloatProgressWidget',\n",
80 70 " 'FloatSliderWidget',\n",
81 71 " 'FloatTextWidget',\n",
82 72 " 'HTMLWidget',\n",
83 73 " 'ImageWidget',\n",
84 74 " 'IntProgressWidget',\n",
85 75 " 'IntSliderWidget',\n",
86 76 " 'IntTextWidget',\n",
87 77 " 'LatexWidget',\n",
88 78 " 'PopupWidget',\n",
89 79 " 'RadioButtonsWidget',\n",
90 80 " 'SelectWidget',\n",
91 81 " 'TabWidget',\n",
92 82 " 'TextWidget',\n",
93 83 " 'TextareaWidget',\n",
94 84 " 'ToggleButtonWidget',\n",
95 85 " 'ToggleButtonsWidget',\n",
96 86 " 'Widget']"
97 87 ]
98 88 }
99 89 ],
100 90 "prompt_number": 1
101 91 },
102 92 {
103 93 "cell_type": "heading",
104 94 "level": 2,
105 95 "metadata": {
106 96 "slideshow": {
107 97 "slide_type": "slide"
108 98 }
109 99 },
110 100 "source": [
111 101 "Numeric widgets"
112 102 ]
113 103 },
114 104 {
115 105 "cell_type": "markdown",
116 106 "metadata": {},
117 107 "source": [
118 108 "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."
119 109 ]
120 110 },
121 111 {
122 112 "cell_type": "heading",
123 113 "level": 3,
124 114 "metadata": {
125 115 "slideshow": {
126 116 "slide_type": "slide"
127 117 }
128 118 },
129 119 "source": [
130 120 "FloatSliderWidget"
131 121 ]
132 122 },
133 123 {
134 124 "cell_type": "code",
135 125 "collapsed": false,
136 126 "input": [
137 127 "widgets.FloatSliderWidget(\n",
138 128 " value=7.5,\n",
139 129 " min=5.0,\n",
140 130 " max=10.0,\n",
141 131 " step=0.1,\n",
142 132 " description='Test:',\n",
143 133 ")"
144 134 ],
145 135 "language": "python",
146 136 "metadata": {},
147 137 "outputs": [],
148 138 "prompt_number": 2
149 139 },
150 140 {
151 141 "cell_type": "markdown",
152 142 "metadata": {},
153 143 "source": [
154 144 "Sliders can also be **displayed vertically**."
155 145 ]
156 146 },
157 147 {
158 148 "cell_type": "code",
159 149 "collapsed": false,
160 150 "input": [
161 151 "widgets.FloatSliderWidget(\n",
162 152 " value=7.5,\n",
163 153 " min=5.0,\n",
164 154 " max=10.0,\n",
165 155 " step=0.1,\n",
166 156 " description='Test',\n",
167 157 " orientation='vertical',\n",
168 158 ")"
169 159 ],
170 160 "language": "python",
171 161 "metadata": {},
172 162 "outputs": [],
173 163 "prompt_number": 3
174 164 },
175 165 {
176 166 "cell_type": "heading",
177 167 "level": 3,
178 168 "metadata": {
179 169 "slideshow": {
180 170 "slide_type": "slide"
181 171 }
182 172 },
183 173 "source": [
184 174 "FloatProgressWidget"
185 175 ]
186 176 },
187 177 {
188 178 "cell_type": "code",
189 179 "collapsed": false,
190 180 "input": [
191 181 "widgets.FloatProgressWidget(\n",
192 182 " value=7.5,\n",
193 183 " min=5.0,\n",
194 184 " max=10.0,\n",
195 185 " step=0.1,\n",
196 186 " description='Loading:',\n",
197 187 ")"
198 188 ],
199 189 "language": "python",
200 190 "metadata": {},
201 191 "outputs": [],
202 192 "prompt_number": 4
203 193 },
204 194 {
205 195 "cell_type": "heading",
206 196 "level": 3,
207 197 "metadata": {
208 198 "slideshow": {
209 199 "slide_type": "slide"
210 200 }
211 201 },
212 202 "source": [
213 203 "BoundedFloatTextWidget"
214 204 ]
215 205 },
216 206 {
217 207 "cell_type": "code",
218 208 "collapsed": false,
219 209 "input": [
220 210 "widgets.BoundedFloatTextWidget(\n",
221 211 " value=7.5,\n",
222 212 " min=5.0,\n",
223 213 " max=10.0,\n",
224 214 " description='Text:',\n",
225 215 ")"
226 216 ],
227 217 "language": "python",
228 218 "metadata": {},
229 219 "outputs": [],
230 220 "prompt_number": 5
231 221 },
232 222 {
233 223 "cell_type": "heading",
234 224 "level": 3,
235 225 "metadata": {
236 226 "slideshow": {
237 227 "slide_type": "slide"
238 228 }
239 229 },
240 230 "source": [
241 231 "FloatTextWidget"
242 232 ]
243 233 },
244 234 {
245 235 "cell_type": "code",
246 236 "collapsed": false,
247 237 "input": [
248 238 "widgets.FloatTextWidget(\n",
249 239 " value=7.5,\n",
250 240 " description='Any:',\n",
251 241 ")"
252 242 ],
253 243 "language": "python",
254 244 "metadata": {},
255 245 "outputs": [],
256 246 "prompt_number": 6
257 247 },
258 248 {
259 249 "cell_type": "heading",
260 250 "level": 2,
261 251 "metadata": {
262 252 "slideshow": {
263 253 "slide_type": "slide"
264 254 }
265 255 },
266 256 "source": [
267 257 "Boolean widgets"
268 258 ]
269 259 },
270 260 {
271 261 "cell_type": "markdown",
272 262 "metadata": {},
273 263 "source": [
274 264 "There are two widgets that are designed to display a boolean value."
275 265 ]
276 266 },
277 267 {
278 268 "cell_type": "heading",
279 269 "level": 3,
280 270 "metadata": {},
281 271 "source": [
282 272 "ToggleButtonWidget"
283 273 ]
284 274 },
285 275 {
286 276 "cell_type": "code",
287 277 "collapsed": false,
288 278 "input": [
289 279 "widgets.ToggleButtonWidget(\n",
290 280 " description='Click me',\n",
291 281 " value=False,\n",
292 282 ")"
293 283 ],
294 284 "language": "python",
295 285 "metadata": {},
296 286 "outputs": [],
297 287 "prompt_number": 7
298 288 },
299 289 {
300 290 "cell_type": "heading",
301 291 "level": 3,
302 292 "metadata": {
303 293 "slideshow": {
304 294 "slide_type": "slide"
305 295 }
306 296 },
307 297 "source": [
308 298 "CheckboxWidget"
309 299 ]
310 300 },
311 301 {
312 302 "cell_type": "code",
313 303 "collapsed": false,
314 304 "input": [
315 305 "widgets.CheckboxWidget(\n",
316 306 " description='Check me',\n",
317 307 " value=True,\n",
318 308 ")"
319 309 ],
320 310 "language": "python",
321 311 "metadata": {},
322 312 "outputs": [],
323 313 "prompt_number": 8
324 314 },
325 315 {
326 316 "cell_type": "heading",
327 317 "level": 2,
328 318 "metadata": {
329 319 "slideshow": {
330 320 "slide_type": "slide"
331 321 }
332 322 },
333 323 "source": [
334 324 "Selection widgets"
335 325 ]
336 326 },
337 327 {
338 328 "cell_type": "markdown",
339 329 "metadata": {},
340 330 "source": [
341 331 "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."
342 332 ]
343 333 },
344 334 {
345 335 "cell_type": "heading",
346 336 "level": 3,
347 337 "metadata": {
348 338 "slideshow": {
349 339 "slide_type": "slide"
350 340 }
351 341 },
352 342 "source": [
353 343 "DropdownWidget"
354 344 ]
355 345 },
356 346 {
357 347 "cell_type": "code",
358 348 "collapsed": false,
359 349 "input": [
360 350 "from IPython.display import display\n",
361 351 "w = widgets.DropdownWidget(\n",
362 352 " values=[1, 2, 3],\n",
363 353 " value=2,\n",
364 354 " description='Number:',\n",
365 355 ")\n",
366 356 "display(w)"
367 357 ],
368 358 "language": "python",
369 359 "metadata": {},
370 360 "outputs": [],
371 361 "prompt_number": 9
372 362 },
373 363 {
374 364 "cell_type": "code",
375 365 "collapsed": false,
376 366 "input": [
377 367 "w.value"
378 368 ],
379 369 "language": "python",
380 370 "metadata": {},
381 371 "outputs": [
382 372 {
383 373 "metadata": {},
384 374 "output_type": "pyout",
385 375 "prompt_number": 10,
386 376 "text": [
387 377 "2"
388 378 ]
389 379 }
390 380 ],
391 381 "prompt_number": 10
392 382 },
393 383 {
394 384 "cell_type": "markdown",
395 385 "metadata": {},
396 386 "source": [
397 387 "The following is also valid:"
398 388 ]
399 389 },
400 390 {
401 391 "cell_type": "code",
402 392 "collapsed": false,
403 393 "input": [
404 394 "w = widgets.DropdownWidget(\n",
405 395 " values={'One': 1, 'Two': 2, 'Three': 3},\n",
406 396 " value=2,\n",
407 397 " description='Number:',\n",
408 398 ")\n",
409 399 "display(w)"
410 400 ],
411 401 "language": "python",
412 402 "metadata": {},
413 403 "outputs": [],
414 404 "prompt_number": 11
415 405 },
416 406 {
417 407 "cell_type": "code",
418 408 "collapsed": false,
419 409 "input": [
420 410 "w.value"
421 411 ],
422 412 "language": "python",
423 413 "metadata": {},
424 414 "outputs": [
425 415 {
426 416 "metadata": {},
427 417 "output_type": "pyout",
428 418 "prompt_number": 12,
429 419 "text": [
430 420 "2"
431 421 ]
432 422 }
433 423 ],
434 424 "prompt_number": 12
435 425 },
436 426 {
437 427 "cell_type": "heading",
438 428 "level": 3,
439 429 "metadata": {
440 430 "slideshow": {
441 431 "slide_type": "slide"
442 432 }
443 433 },
444 434 "source": [
445 435 "RadioButtonsWidget"
446 436 ]
447 437 },
448 438 {
449 439 "cell_type": "code",
450 440 "collapsed": false,
451 441 "input": [
452 442 "widgets.RadioButtonsWidget(\n",
453 443 " description='Pizza topping:',\n",
454 444 " values=['pepperoni', 'pineapple', 'anchovies'],\n",
455 445 ")"
456 446 ],
457 447 "language": "python",
458 448 "metadata": {},
459 449 "outputs": [],
460 450 "prompt_number": 13
461 451 },
462 452 {
463 453 "cell_type": "heading",
464 454 "level": 3,
465 455 "metadata": {
466 456 "slideshow": {
467 457 "slide_type": "slide"
468 458 }
469 459 },
470 460 "source": [
471 461 "SelectWidget"
472 462 ]
473 463 },
474 464 {
475 465 "cell_type": "code",
476 466 "collapsed": false,
477 467 "input": [
478 468 "widgets.SelectWidget(\n",
479 469 " description='OS:',\n",
480 470 " values=['Linux', 'Windows', 'OSX'],\n",
481 471 ")"
482 472 ],
483 473 "language": "python",
484 474 "metadata": {},
485 475 "outputs": [],
486 476 "prompt_number": 14
487 477 },
488 478 {
489 479 "cell_type": "heading",
490 480 "level": 3,
491 481 "metadata": {
492 482 "slideshow": {
493 483 "slide_type": "slide"
494 484 }
495 485 },
496 486 "source": [
497 487 "ToggleButtonsWidget"
498 488 ]
499 489 },
500 490 {
501 491 "cell_type": "code",
502 492 "collapsed": false,
503 493 "input": [
504 494 "widgets.ToggleButtonsWidget(\n",
505 495 " description='Speed:',\n",
506 496 " values=['Slow', 'Regular', 'Fast'],\n",
507 497 ")"
508 498 ],
509 499 "language": "python",
510 500 "metadata": {},
511 501 "outputs": [],
512 502 "prompt_number": 15
513 503 },
514 504 {
515 505 "cell_type": "heading",
516 506 "level": 2,
517 507 "metadata": {
518 508 "slideshow": {
519 509 "slide_type": "slide"
520 510 }
521 511 },
522 512 "source": [
523 513 "String widgets"
524 514 ]
525 515 },
526 516 {
527 517 "cell_type": "markdown",
528 518 "metadata": {},
529 519 "source": [
530 520 "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**."
531 521 ]
532 522 },
533 523 {
534 524 "cell_type": "heading",
535 525 "level": 3,
536 526 "metadata": {
537 527 "slideshow": {
538 528 "slide_type": "slide"
539 529 }
540 530 },
541 531 "source": [
542 532 "TextWidget"
543 533 ]
544 534 },
545 535 {
546 536 "cell_type": "code",
547 537 "collapsed": false,
548 538 "input": [
549 539 "widgets.TextWidget(\n",
550 540 " description='String:',\n",
551 541 " value='Hello World',\n",
552 542 ")"
553 543 ],
554 544 "language": "python",
555 545 "metadata": {},
556 546 "outputs": [],
557 547 "prompt_number": 16
558 548 },
559 549 {
560 550 "cell_type": "heading",
561 551 "level": 3,
562 552 "metadata": {},
563 553 "source": [
564 554 "TextareaWidget"
565 555 ]
566 556 },
567 557 {
568 558 "cell_type": "code",
569 559 "collapsed": false,
570 560 "input": [
571 561 "widgets.TextareaWidget(\n",
572 562 " description='String:',\n",
573 563 " value='Hello World',\n",
574 564 ")"
575 565 ],
576 566 "language": "python",
577 567 "metadata": {},
578 568 "outputs": [],
579 569 "prompt_number": 17
580 570 },
581 571 {
582 572 "cell_type": "heading",
583 573 "level": 3,
584 574 "metadata": {
585 575 "slideshow": {
586 576 "slide_type": "slide"
587 577 }
588 578 },
589 579 "source": [
590 580 "LatexWidget"
591 581 ]
592 582 },
593 583 {
594 584 "cell_type": "code",
595 585 "collapsed": false,
596 586 "input": [
597 587 "widgets.LatexWidget(\n",
598 588 " value=\"$$\\\\frac{n!}{k!(n-k)!} = \\\\binom{n}{k}$$\",\n",
599 589 ")"
600 590 ],
601 591 "language": "python",
602 592 "metadata": {},
603 593 "outputs": [],
604 594 "prompt_number": 18
605 595 },
606 596 {
607 597 "cell_type": "heading",
608 598 "level": 3,
609 599 "metadata": {},
610 600 "source": [
611 601 "HTMLWidget"
612 602 ]
613 603 },
614 604 {
615 605 "cell_type": "code",
616 606 "collapsed": false,
617 607 "input": [
618 608 "widgets.HTMLWidget(\n",
619 609 " value=\"Hello <b>World</b>\"\n",
620 610 ")"
621 611 ],
622 612 "language": "python",
623 613 "metadata": {},
624 614 "outputs": [],
625 615 "prompt_number": 20
626 616 },
627 617 {
628 618 "cell_type": "heading",
629 619 "level": 2,
630 620 "metadata": {
631 621 "slideshow": {
632 622 "slide_type": "slide"
633 623 }
634 624 },
635 625 "source": [
636 626 "ButtonWidget"
637 627 ]
638 628 },
639 629 {
640 630 "cell_type": "code",
641 631 "collapsed": false,
642 632 "input": [
643 633 "widgets.ButtonWidget(description='Click me')"
644 634 ],
645 635 "language": "python",
646 636 "metadata": {},
647 637 "outputs": [],
648 638 "prompt_number": 21
649 639 },
650 640 {
651 641 "cell_type": "markdown",
652 642 "metadata": {},
653 643 "source": [
654 644 "[Index](Index.ipynb) - [Back](Widget Basics.ipynb) - [Next](Widget Events.ipynb)"
655 645 ]
656 646 }
657 647 ],
658 648 "metadata": {}
659 649 }
660 650 ]
661 651 } No newline at end of file
@@ -1,1283 +1,1465 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:98ca4ae261d3dc9c0b43b3fa822772a47fff9956e443c640b2caead8d02efece"
11 "signature": "sha256:6ee07cf9871c5a2431610eb8a2a5057f9e669769932696690f70967b255fbea7"
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 "div.text_cell.cell.rendered.slideshow-slide { margin-top: 5em !important; } // Slideshow styling.\n",
32 31 ".example-container { background: #999999; padding: 2px; min-height: 100px; }\n",
33 32 ".example-container.sm { min-height: 50px; }\n",
34 33 ".example-box { background: #9999FF; width: 50px; height: 50px; text-align: center; vertical-align: middle; color: white; font-weight: bold; margin: 2px;}\n",
35 34 ".example-box.med { width: 65px; height: 65px; } \n",
36 35 ".example-box.lrg { width: 80px; height: 80px; } \n",
37 36 "</style>"
38 37 ],
39 38 "language": "python",
40 39 "metadata": {},
41 40 "outputs": [
42 41 {
43 42 "html": [
44 43 "<style>\n",
45 "div.text_cell.cell.rendered.slideshow-slide { margin-top: 5em !important; } // Slideshow styling.\n",
46 44 ".example-container { background: #999999; padding: 2px; min-height: 100px; }\n",
47 45 ".example-container.sm { min-height: 50px; }\n",
48 46 ".example-box { background: #9999FF; width: 50px; height: 50px; text-align: center; vertical-align: middle; color: white; font-weight: bold; margin: 2px;}\n",
49 47 ".example-box.med { width: 65px; height: 65px; } \n",
50 48 ".example-box.lrg { width: 80px; height: 80px; } \n",
51 49 "</style>"
52 50 ],
53 51 "metadata": {},
54 52 "output_type": "display_data",
55 53 "text": [
56 54 "<IPython.core.display.HTML object>"
57 55 ]
58 56 }
59 57 ],
60 "prompt_number": 1
58 "prompt_number": 6
61 59 },
62 60 {
63 61 "cell_type": "heading",
64 62 "level": 1,
65 63 "metadata": {
66 64 "slideshow": {
67 65 "slide_type": "slide"
68 66 }
69 67 },
70 68 "source": [
71 69 "Widget Styling"
72 70 ]
73 71 },
74 72 {
75 73 "cell_type": "heading",
76 74 "level": 2,
77 75 "metadata": {},
78 76 "source": [
79 77 "CSS"
80 78 ]
81 79 },
82 80 {
83 81 "cell_type": "markdown",
84 82 "metadata": {},
85 83 "source": [
86 84 "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`."
87 85 ]
88 86 },
89 87 {
90 88 "cell_type": "code",
91 89 "collapsed": false,
92 90 "input": [
93 91 "from IPython.html import widgets\n",
94 92 "text = widgets.TextWidget()\n",
95 93 "text.set_css('background', 'lime')\n",
96 94 "text "
97 95 ],
98 96 "language": "python",
99 97 "metadata": {},
100 98 "outputs": [],
101 "prompt_number": 2
99 "prompt_number": 7
102 100 },
103 101 {
104 102 "cell_type": "heading",
105 103 "level": 3,
106 104 "metadata": {
107 105 "slideshow": {
108 106 "slide_type": "slide"
109 107 }
110 108 },
111 109 "source": [
112 110 "Color codes"
113 111 ]
114 112 },
115 113 {
116 114 "cell_type": "markdown",
117 115 "metadata": {},
118 116 "source": [
119 117 "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."
120 118 ]
121 119 },
122 120 {
123 121 "cell_type": "code",
124 122 "collapsed": false,
125 123 "input": [
126 124 "text.set_css('background', '#0000FF')"
127 125 ],
128 126 "language": "python",
129 127 "metadata": {},
130 128 "outputs": [],
131 "prompt_number": 3
129 "prompt_number": 8
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 "Forecolor"
143 141 ]
144 142 },
145 143 {
146 144 "cell_type": "markdown",
147 145 "metadata": {},
148 146 "source": [
149 147 "In CSS the **font color is `color`.**"
150 148 ]
151 149 },
152 150 {
153 151 "cell_type": "code",
154 152 "collapsed": false,
155 153 "input": [
156 154 "text.set_css('color', '#FFFFFF')"
157 155 ],
158 156 "language": "python",
159 157 "metadata": {},
160 158 "outputs": [],
161 "prompt_number": 4
159 "prompt_number": 9
162 160 },
163 161 {
164 162 "cell_type": "heading",
165 163 "level": 3,
166 164 "metadata": {
167 165 "slideshow": {
168 166 "slide_type": "slide"
169 167 }
170 168 },
171 169 "source": [
172 170 "Size"
173 171 ]
174 172 },
175 173 {
176 174 "cell_type": "markdown",
177 175 "metadata": {},
178 176 "source": [
179 177 "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)."
180 178 ]
181 179 },
182 180 {
183 181 "cell_type": "code",
184 182 "collapsed": false,
185 183 "input": [
186 184 "btn = widgets.ButtonWidget()\n",
187 185 "btn.set_css({\n",
188 186 " 'width': '100px',\n",
189 187 " 'height': '100px',\n",
188 " 'background': 'red',\n",
190 189 "})\n",
191 190 "btn"
192 191 ],
193 192 "language": "python",
194 193 "metadata": {},
195 194 "outputs": [],
196 "prompt_number": 6
195 "prompt_number": 12
197 196 },
198 197 {
199 198 "cell_type": "heading",
200 199 "level": 3,
201 200 "metadata": {
202 201 "slideshow": {
203 202 "slide_type": "slide"
204 203 }
205 204 },
206 205 "source": [
207 206 "Removing"
208 207 ]
209 208 },
210 209 {
211 210 "cell_type": "markdown",
212 211 "metadata": {},
213 212 "source": [
214 213 "To remove the styling, you can call `set_css` again, but use an empty string instead of a color value."
215 214 ]
216 215 },
217 216 {
218 217 "cell_type": "code",
219 218 "collapsed": false,
220 219 "input": [
221 "text.set_css('background', '')"
220 "btn.set_css('background', '')"
222 221 ],
223 222 "language": "python",
224 223 "metadata": {},
225 224 "outputs": [],
226 "prompt_number": 5
225 "prompt_number": 13
227 226 },
228 227 {
229 228 "cell_type": "markdown",
230 229 "metadata": {},
231 230 "source": [
232 231 "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"
233 232 ]
234 233 },
235 234 {
236 235 "cell_type": "heading",
237 236 "level": 2,
238 237 "metadata": {
239 238 "slideshow": {
240 239 "slide_type": "slide"
241 240 }
242 241 },
243 242 "source": [
244 243 "Parent/child relationships"
245 244 ]
246 245 },
247 246 {
248 247 "cell_type": "markdown",
249 248 "metadata": {},
250 249 "source": [
251 250 "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",
252 251 "\n",
253 252 "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."
254 253 ]
255 254 },
256 255 {
257 256 "cell_type": "code",
258 257 "collapsed": false,
259 258 "input": [
260 259 "\n",
261 260 "from IPython.display import display\n",
262 261 "\n",
263 262 "float_range = widgets.FloatSliderWidget()\n",
264 263 "string = widgets.TextWidget(value='hi')\n",
265 264 "container = widgets.ContainerWidget(children=[float_range, string])\n",
266 265 "\n",
267 266 "container.set_css('border', '3px dotted red')\n",
268 267 "display(container) # Displays the `container` and all of it's children."
269 268 ],
270 269 "language": "python",
271 270 "metadata": {},
272 271 "outputs": [],
273 "prompt_number": 7
272 "prompt_number": 14
273 },
274 {
275 "cell_type": "heading",
276 "level": 3,
277 "metadata": {},
278 "source": [
279 "After the parent is displayed"
280 ]
274 281 },
275 282 {
276 283 "cell_type": "markdown",
277 284 "metadata": {
278 285 "slideshow": {
279 286 "slide_type": "slide"
280 287 }
281 288 },
282 289 "source": [
283 "### After the parent is displayed\n",
284 290 "Children **can be added to parents** after the parent has been displayed. The **parent is responsible for rendering its children**."
285 291 ]
286 292 },
287 293 {
288 294 "cell_type": "code",
289 295 "collapsed": false,
290 296 "input": [
291 297 "container = widgets.ContainerWidget()\n",
292 298 "container.set_css('border', '3px dotted red')\n",
293 299 "display(container)\n",
294 300 "\n",
295 301 "int_range = widgets.IntSliderWidget()\n",
296 302 "container.children=[int_range]"
297 303 ],
298 304 "language": "python",
299 305 "metadata": {},
300 306 "outputs": [],
301 "prompt_number": 8
307 "prompt_number": 15
302 308 },
303 309 {
304 310 "cell_type": "heading",
305 311 "level": 2,
306 312 "metadata": {
307 313 "slideshow": {
308 314 "slide_type": "slide"
309 315 }
310 316 },
311 317 "source": [
312 318 "Fancy containers"
313 319 ]
314 320 },
315 321 {
316 322 "cell_type": "markdown",
317 323 "metadata": {},
318 324 "source": [
319 325 "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**."
320 326 ]
321 327 },
322 328 {
323 329 "cell_type": "heading",
324 330 "level": 3,
325 331 "metadata": {},
326 332 "source": [
327 333 "AccordionWidget"
328 334 ]
329 335 },
330 336 {
331 337 "cell_type": "code",
332 338 "collapsed": false,
333 339 "input": [
334 340 "name1 = widgets.TextWidget(description='Location:')\n",
335 341 "zip1 = widgets.BoundedIntTextWidget(description='Zip:', min=0, max=99999)\n",
336 342 "page1 = widgets.ContainerWidget(children=[name1, zip1])\n",
337 343 "\n",
338 344 "name2 = widgets.TextWidget(description='Location:')\n",
339 345 "zip2 = widgets.BoundedIntTextWidget(description='Zip:', min=0, max=99999)\n",
340 346 "page2 = widgets.ContainerWidget(children=[name2, zip2])\n",
341 347 "\n",
342 348 "accord = widgets.AccordionWidget(children=[page1, page2])\n",
343 349 "display(accord)\n",
344 350 "\n",
345 351 "accord.set_title(0, 'From')\n",
346 352 "accord.set_title(1, 'To')"
347 353 ],
348 354 "language": "python",
349 355 "metadata": {},
350 356 "outputs": [],
351 "prompt_number": 9
357 "prompt_number": 16
352 358 },
353 359 {
354 360 "cell_type": "heading",
355 361 "level": 3,
356 362 "metadata": {
357 363 "slideshow": {
358 364 "slide_type": "slide"
359 365 }
360 366 },
361 367 "source": [
362 368 "TabWidget"
363 369 ]
364 370 },
365 371 {
366 372 "cell_type": "code",
367 373 "collapsed": false,
368 374 "input": [
369 375 "name = widgets.TextWidget(description='Name:')\n",
370 376 "color = widgets.DropdownWidget(description='Color:', values=['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'])\n",
371 377 "page1 = widgets.ContainerWidget(children=[name, color])\n",
372 378 "\n",
373 379 "age = widgets.IntSliderWidget(description='Age:', min=0, max=120, value=50)\n",
374 380 "gender = widgets.RadioButtonsWidget(description='Gender:', values=['male', 'female'])\n",
375 381 "page2 = widgets.ContainerWidget(children=[age, gender])\n",
376 382 "\n",
377 383 "tabs = widgets.TabWidget(children=[page1, page2])\n",
378 384 "display(tabs)\n",
379 385 "\n",
380 386 "tabs.set_title(0, 'Name')\n",
381 387 "tabs.set_title(1, 'Details')"
382 388 ],
383 389 "language": "python",
384 390 "metadata": {},
385 391 "outputs": [],
386 "prompt_number": 10
392 "prompt_number": 17
387 393 },
388 394 {
389 395 "cell_type": "heading",
390 396 "level": 3,
391 397 "metadata": {
392 398 "slideshow": {
393 399 "slide_type": "slide"
394 400 }
395 401 },
396 402 "source": [
397 403 "PopupWidget"
398 404 ]
399 405 },
400 406 {
401 407 "cell_type": "markdown",
402 408 "metadata": {},
403 409 "source": [
404 410 "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**. "
405 411 ]
406 412 },
407 413 {
408 414 "cell_type": "code",
409 415 "collapsed": false,
410 416 "input": [
411 417 "counter = widgets.IntTextWidget(description='Counter:')\n",
412 418 "popup = widgets.PopupWidget(children=[counter], description='Popup Demo', button_text='Popup Button')\n",
413 419 "display(popup)"
414 420 ],
415 421 "language": "python",
416 422 "metadata": {},
417 423 "outputs": [],
418 "prompt_number": 11
424 "prompt_number": 18
419 425 },
420 426 {
421 427 "cell_type": "code",
422 428 "collapsed": false,
423 429 "input": [
424 430 "counter.value += 1"
425 431 ],
426 432 "language": "python",
427 433 "metadata": {},
428 434 "outputs": [],
429 "prompt_number": 12
435 "prompt_number": 19
430 436 },
431 437 {
432 438 "cell_type": "code",
433 439 "collapsed": false,
434 440 "input": [],
435 441 "language": "python",
436 442 "metadata": {},
437 443 "outputs": [],
438 "prompt_number": 12
444 "prompt_number": 19
439 445 },
440 446 {
441 447 "cell_type": "code",
442 448 "collapsed": false,
443 449 "input": [],
444 450 "language": "python",
445 451 "metadata": {},
446 452 "outputs": [],
447 "prompt_number": 12
453 "prompt_number": 19
448 454 },
449 455 {
450 456 "cell_type": "code",
451 457 "collapsed": false,
452 458 "input": [],
453 459 "language": "python",
454 460 "metadata": {},
455 461 "outputs": [],
456 "prompt_number": 12
462 "prompt_number": 19
457 463 },
458 464 {
459 465 "cell_type": "code",
460 466 "collapsed": false,
461 467 "input": [],
462 468 "language": "python",
463 469 "metadata": {},
464 470 "outputs": [],
465 "prompt_number": 12
471 "prompt_number": 19
466 472 },
467 473 {
468 474 "cell_type": "code",
469 475 "collapsed": false,
470 476 "input": [],
471 477 "language": "python",
472 478 "metadata": {},
473 479 "outputs": [],
474 "prompt_number": 12
480 "prompt_number": 19
475 481 },
476 482 {
477 483 "cell_type": "code",
478 484 "collapsed": false,
479 485 "input": [],
480 486 "language": "python",
481 487 "metadata": {},
482 488 "outputs": [],
483 "prompt_number": 12
489 "prompt_number": 19
484 490 },
485 491 {
486 492 "cell_type": "code",
487 493 "collapsed": false,
488 494 "input": [],
489 495 "language": "python",
490 496 "metadata": {},
491 497 "outputs": [],
492 "prompt_number": 12
498 "prompt_number": 19
493 499 },
494 500 {
495 501 "cell_type": "code",
496 502 "collapsed": false,
497 503 "input": [],
498 504 "language": "python",
499 505 "metadata": {},
500 506 "outputs": [],
501 "prompt_number": 12
507 "prompt_number": 19
502 508 },
503 509 {
504 510 "cell_type": "code",
505 511 "collapsed": false,
506 512 "input": [],
507 513 "language": "python",
508 514 "metadata": {},
509 515 "outputs": [],
510 "prompt_number": 12
516 "prompt_number": 19
511 517 },
512 518 {
513 519 "cell_type": "code",
514 520 "collapsed": false,
515 521 "input": [],
516 522 "language": "python",
517 523 "metadata": {},
518 524 "outputs": [],
519 "prompt_number": 12
525 "prompt_number": 19
520 526 },
521 527 {
522 528 "cell_type": "code",
523 529 "collapsed": false,
524 530 "input": [],
525 531 "language": "python",
526 532 "metadata": {},
527 533 "outputs": [],
528 "prompt_number": 12
534 "prompt_number": 19
529 535 },
530 536 {
531 537 "cell_type": "code",
532 538 "collapsed": false,
533 539 "input": [],
534 540 "language": "python",
535 541 "metadata": {},
536 542 "outputs": [],
537 "prompt_number": 12
543 "prompt_number": 19
538 544 },
539 545 {
540 546 "cell_type": "code",
541 547 "collapsed": false,
542 548 "input": [],
543 549 "language": "python",
544 550 "metadata": {},
545 551 "outputs": [],
546 "prompt_number": 12
552 "prompt_number": 19
547 553 },
548 554 {
549 555 "cell_type": "code",
550 556 "collapsed": false,
551 557 "input": [],
552 558 "language": "python",
553 559 "metadata": {},
554 560 "outputs": [],
555 "prompt_number": 12
561 "prompt_number": 19
556 562 },
557 563 {
558 564 "cell_type": "code",
559 565 "collapsed": false,
560 566 "input": [
561 567 "counter.value += 1"
562 568 ],
563 569 "language": "python",
564 570 "metadata": {},
565 571 "outputs": [],
566 "prompt_number": 13
572 "prompt_number": 20
567 573 },
568 574 {
569 575 "cell_type": "code",
570 576 "collapsed": false,
571 577 "input": [
572 578 "popup.close()"
573 579 ],
574 580 "language": "python",
575 581 "metadata": {},
576 582 "outputs": [],
577 "prompt_number": 14
583 "prompt_number": 21
578 584 },
579 585 {
580 586 "cell_type": "heading",
581 587 "level": 1,
582 588 "metadata": {
583 589 "slideshow": {
584 590 "slide_type": "slide"
585 591 }
586 592 },
587 593 "source": [
588 594 "Alignment"
589 595 ]
590 596 },
591 597 {
592 598 "cell_type": "markdown",
593 599 "metadata": {},
594 600 "source": [
595 601 "Most widgets have a **`description` attribute**, which allows a label for the widget to be defined.\n",
596 602 "The label of the widget **has a fixed minimum width**.\n",
597 603 "The text of the label is **always right aligned and the widget is left aligned**:"
598 604 ]
599 605 },
600 606 {
601 607 "cell_type": "code",
602 608 "collapsed": false,
603 609 "input": [
604 610 "display(widgets.TextWidget(description=\"a:\"))\n",
605 611 "display(widgets.TextWidget(description=\"aa:\"))\n",
606 612 "display(widgets.TextWidget(description=\"aaa:\"))"
607 613 ],
608 614 "language": "python",
609 615 "metadata": {},
610 "outputs": [
611 {
612 "ename": "NameError",
613 "evalue": "name 'display' is not defined",
614 "output_type": "pyerr",
615 "traceback": [
616 "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
617 "\u001b[0;32m<ipython-input-4-66f52ebe0195>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mdisplay\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mwidgets\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTextWidget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdescription\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"a:\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0mdisplay\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mwidgets\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTextWidget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdescription\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"aa:\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mdisplay\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mwidgets\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTextWidget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdescription\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"aaa:\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
618 "\u001b[0;31mNameError\u001b[0m: name 'display' is not defined"
619 ]
620 }
621 ],
622 "prompt_number": 4
616 "outputs": [],
617 "prompt_number": 22
623 618 },
624 619 {
625 620 "cell_type": "markdown",
626 621 "metadata": {
627 622 "slideshow": {
628 623 "slide_type": "slide"
629 624 }
630 625 },
631 626 "source": [
632 627 "If a **label is longer** than the minimum width, the **widget is shifted to the right**:"
633 628 ]
634 629 },
635 630 {
636 631 "cell_type": "code",
637 632 "collapsed": false,
638 633 "input": [
639 634 "display(widgets.TextWidget(description=\"a:\"))\n",
640 635 "display(widgets.TextWidget(description=\"aa:\"))\n",
641 636 "display(widgets.TextWidget(description=\"aaa:\"))\n",
642 637 "display(widgets.TextWidget(description=\"aaaaaaaaaaaaaaaaaa:\"))"
643 638 ],
644 639 "language": "python",
645 640 "metadata": {},
646 "outputs": [
647 {
648 "ename": "NameError",
649 "evalue": "name 'display' is not defined",
650 "output_type": "pyerr",
651 "traceback": [
652 "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
653 "\u001b[0;32m<ipython-input-3-bd60a4ccdeb5>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mdisplay\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mwidgets\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTextWidget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdescription\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"a:\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0mdisplay\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mwidgets\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTextWidget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdescription\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"aa:\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mdisplay\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mwidgets\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTextWidget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdescription\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"aaa:\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mdisplay\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mwidgets\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTextWidget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdescription\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"aaaaaaaaaaaaaaaaaa:\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
654 "\u001b[0;31mNameError\u001b[0m: name 'display' is not defined"
655 ]
656 }
657 ],
658 "prompt_number": 3
641 "outputs": [],
642 "prompt_number": 23
659 643 },
660 644 {
661 645 "cell_type": "markdown",
662 646 "metadata": {
663 647 "slideshow": {
664 648 "slide_type": "slide"
665 649 }
666 650 },
667 651 "source": [
668 652 "If a `description` is **not set** for the widget, the **label is not displayed**:"
669 653 ]
670 654 },
671 655 {
672 656 "cell_type": "code",
673 657 "collapsed": false,
674 658 "input": [
675 659 "display(widgets.TextWidget(description=\"a:\"))\n",
676 660 "display(widgets.TextWidget(description=\"aa:\"))\n",
677 661 "display(widgets.TextWidget(description=\"aaa:\"))\n",
678 662 "display(widgets.TextWidget())"
679 663 ],
680 664 "language": "python",
681 665 "metadata": {},
682 666 "outputs": [],
683 "prompt_number": 17
667 "prompt_number": 24
684 668 },
685 669 {
686 670 "cell_type": "heading",
687 671 "level": 1,
688 672 "metadata": {
689 673 "slideshow": {
690 674 "slide_type": "slide"
691 675 }
692 676 },
693 677 "source": [
694 678 "DOM Classes"
695 679 ]
696 680 },
697 681 {
698 682 "cell_type": "markdown",
699 683 "metadata": {},
700 684 "source": [
701 685 "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/)."
702 686 ]
703 687 },
704 688 {
705 689 "cell_type": "heading",
706 690 "level": 2,
707 691 "metadata": {
708 692 "slideshow": {
709 693 "slide_type": "slide"
710 694 }
711 695 },
712 696 "source": [
713 697 "Path dependent"
714 698 ]
715 699 },
716 700 {
717 701 "cell_type": "markdown",
718 702 "metadata": {},
719 703 "source": [
720 704 "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.**"
721 705 ]
722 706 },
723 707 {
724 708 "cell_type": "code",
725 709 "collapsed": false,
726 710 "input": [
727 711 "%%html\n",
728 712 "<style>\n",
729 713 " div.cube { display: inline; padding: 5px; }\n",
730 714 " div.red { background: red; }\n",
731 715 " div.blue { background: blue; }\n",
732 716 "</style>"
733 717 ],
734 718 "language": "python",
735 719 "metadata": {},
736 720 "outputs": [
737 721 {
738 722 "html": [
739 723 "<style>\n",
740 724 " div.cube { display: inline; padding: 5px; }\n",
741 725 " div.red { background: red; }\n",
742 726 " div.blue { background: blue; }\n",
743 727 "</style>"
744 728 ],
745 729 "metadata": {},
746 730 "output_type": "display_data",
747 731 "text": [
748 732 "<IPython.core.display.HTML object>"
749 733 ]
750 734 }
751 735 ],
752 "prompt_number": 18
736 "prompt_number": 25
753 737 },
754 738 {
755 739 "cell_type": "code",
756 740 "collapsed": false,
757 741 "input": [
758 742 "from IPython.html import widgets\n",
759 743 "from IPython.display import display\n",
760 744 "html = '<br />'.join([''.join(['<div class=\"cube\">x</div>' for i in range(8)]) for j in range(8)])\n",
761 745 "widget = [widgets.HTMLWidget(value=html) for i in range(3)]\n",
762 746 "\n",
763 747 "display(widget[0])\n",
764 748 "widget[0].add_class('red', 'div.cube:nth-child(even)')\n",
765 749 "widget[0].remove_class('red', 'div.red:nth-child(7n+1)')\n",
766 750 "widget[0].add_class('blue', 'div.red:nth-child(3n+1)')"
767 751 ],
768 752 "language": "python",
769 753 "metadata": {},
770 754 "outputs": [],
771 "prompt_number": 19
755 "prompt_number": 26
772 756 },
773 757 {
774 758 "cell_type": "code",
775 759 "collapsed": false,
776 760 "input": [
777 761 "display(widget[1])\n",
778 762 "widget[1].remove_class('red', 'div.red:nth-child(7n+1)')\n",
779 763 "widget[1].add_class('blue', 'div.red:nth-child(3n+1)')\n",
780 764 "widget[1].add_class('red', 'div.cube:nth-child(even)')"
781 765 ],
782 766 "language": "python",
783 767 "metadata": {},
784 768 "outputs": [],
785 "prompt_number": 20
769 "prompt_number": 27
786 770 },
787 771 {
788 772 "cell_type": "code",
789 773 "collapsed": false,
790 774 "input": [
791 775 "display(widget[2])\n",
792 776 "widget[2].add_class('red', 'div.cube:nth-child(even)')\n",
793 777 "widget[2].add_class('blue', 'div.red:nth-child(3n+1)')\n",
794 778 "widget[2].remove_class('red', 'div.red:nth-child(7n+1)')"
795 779 ],
796 780 "language": "python",
797 781 "metadata": {},
798 782 "outputs": [],
799 "prompt_number": 21
783 "prompt_number": 28
800 784 },
801 785 {
802 786 "cell_type": "heading",
803 787 "level": 2,
804 788 "metadata": {
805 789 "slideshow": {
806 790 "slide_type": "slide"
807 791 }
808 792 },
809 793 "source": [
810 794 "Alignment classes"
811 795 ]
812 796 },
813 797 {
814 798 "cell_type": "markdown",
815 799 "metadata": {},
816 800 "source": [
817 "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:\n",
818 "\n",
819 "### Orientation classes\n",
820 "#### \"vbox\"\n",
801 "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:"
802 ]
803 },
804 {
805 "cell_type": "heading",
806 "level": 3,
807 "metadata": {},
808 "source": [
809 "Orientation classes"
810 ]
811 },
812 {
813 "cell_type": "heading",
814 "level": 4,
815 "metadata": {},
816 "source": [
817 "\"vbox\""
818 ]
819 },
820 {
821 "cell_type": "markdown",
822 "metadata": {},
823 "source": [
821 824 "Widget containers default to this orientation.\n",
822 825 "<div class=\"example-container vbox\">\n",
823 826 "<div class=\"example-box\">A</div>\n",
824 827 "<div class=\"example-box med\">B</div>\n",
825 828 "<div class=\"example-box lrg\">C</div>\n",
826 "</div>\n",
827 "\n",
828 "#### \"hbox\"\n",
829 "</div>"
830 ]
831 },
832 {
833 "cell_type": "heading",
834 "level": 4,
835 "metadata": {},
836 "source": [
837 "\"hbox\""
838 ]
839 },
840 {
841 "cell_type": "markdown",
842 "metadata": {},
843 "source": [
829 844 "<div class=\"example-container hbox\">\n",
830 845 "<div class=\"example-box\">A</div>\n",
831 846 "<div class=\"example-box med\">B</div>\n",
832 847 "<div class=\"example-box lrg\">C</div>\n",
833 848 "</div>"
834 849 ]
835 850 },
836 851 {
852 "cell_type": "heading",
853 "level": 3,
854 "metadata": {},
855 "source": [
856 "Packing classes"
857 ]
858 },
859 {
837 860 "cell_type": "markdown",
838 "metadata": {
839 "slideshow": {
840 "slide_type": "slide"
841 }
842 },
861 "metadata": {},
862 "source": [
863 "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**."
864 ]
865 },
866 {
867 "cell_type": "heading",
868 "level": 4,
869 "metadata": {},
870 "source": [
871 "\"start\""
872 ]
873 },
874 {
875 "cell_type": "markdown",
876 "metadata": {},
843 877 "source": [
844 "### Packing classes\n",
845 "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**.\n",
846 "#### \"start\"\n",
847 878 "<div class=\"example-container hbox start\">\n",
848 879 "<div class=\"example-box\">A</div>\n",
849 880 "<div class=\"example-box med\">B</div>\n",
850 881 "<div class=\"example-box lrg\">C</div>\n",
851 "</div>\n",
852 "\n",
853 "#### \"center\"\n",
882 "</div>"
883 ]
884 },
885 {
886 "cell_type": "heading",
887 "level": 4,
888 "metadata": {},
889 "source": [
890 "\"center\""
891 ]
892 },
893 {
894 "cell_type": "markdown",
895 "metadata": {},
896 "source": [
854 897 "<div class=\"example-container hbox center\">\n",
855 898 "<div class=\"example-box\">A</div>\n",
856 899 "<div class=\"example-box med\">B</div>\n",
857 900 "<div class=\"example-box lrg\">C</div>\n",
858 "</div>\n",
859 "\n",
860 "#### \"end\"\n",
861 "<div class=\"example-container hbox end\">\n",
862 "<div class=\"example-box\">A</div>\n",
863 "<div class=\"example-box med\">B</div>\n",
864 "<div class=\"example-box lrg\">C</div>\n",
865 901 "</div>"
866 902 ]
867 903 },
868 904 {
905 "cell_type": "heading",
906 "level": 4,
907 "metadata": {},
908 "source": [
909 "\"end\""
910 ]
911 },
912 {
869 913 "cell_type": "markdown",
870 914 "metadata": {
871 915 "slideshow": {
872 916 "slide_type": "slide"
873 917 }
874 918 },
875 919 "source": [
876 "### Aligning classes\n",
877 "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**.\n",
878 "#### \"align-start\"\n",
879 "<div class=\"example-container hbox align-start\">\n",
920 "<div class=\"example-container hbox end\">\n",
880 921 "<div class=\"example-box\">A</div>\n",
881 922 "<div class=\"example-box med\">B</div>\n",
882 923 "<div class=\"example-box lrg\">C</div>\n",
883 "</div>\n",
884 "\n",
885 "#### \"align-center\"\n",
886 "<div class=\"example-container hbox align-center\">\n",
924 "</div>"
925 ]
926 },
927 {
928 "cell_type": "heading",
929 "level": 3,
930 "metadata": {},
931 "source": [
932 "Aligning classes"
933 ]
934 },
935 {
936 "cell_type": "markdown",
937 "metadata": {},
938 "source": [
939 "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**."
940 ]
941 },
942 {
943 "cell_type": "heading",
944 "level": 4,
945 "metadata": {},
946 "source": [
947 "\"align-start\""
948 ]
949 },
950 {
951 "cell_type": "markdown",
952 "metadata": {},
953 "source": [
954 "<div class=\"example-container hbox align-start\">\n",
887 955 "<div class=\"example-box\">A</div>\n",
888 956 "<div class=\"example-box med\">B</div>\n",
889 957 "<div class=\"example-box lrg\">C</div>\n",
890 "</div>\n",
891 "\n",
892 "#### \"align-end\"\n",
893 "<div class=\"example-container hbox align-end\">\n",
958 "</div>"
959 ]
960 },
961 {
962 "cell_type": "heading",
963 "level": 4,
964 "metadata": {},
965 "source": [
966 "\"align-center\""
967 ]
968 },
969 {
970 "cell_type": "markdown",
971 "metadata": {},
972 "source": [
973 "<div class=\"example-container hbox align-center\">\n",
894 974 "<div class=\"example-box\">A</div>\n",
895 975 "<div class=\"example-box med\">B</div>\n",
896 976 "<div class=\"example-box lrg\">C</div>\n",
897 977 "</div>"
898 978 ]
899 979 },
900 980 {
981 "cell_type": "heading",
982 "level": 4,
983 "metadata": {},
984 "source": [
985 "\"align-end\""
986 ]
987 },
988 {
901 989 "cell_type": "markdown",
902 990 "metadata": {
903 991 "slideshow": {
904 992 "slide_type": "slide"
905 993 }
906 994 },
907 995 "source": [
908 "### Flex classes\n",
909 "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.\n",
910 "\n",
911 "#### Example 1\n",
996 "<div class=\"example-container hbox align-end\">\n",
997 "<div class=\"example-box\">A</div>\n",
998 "<div class=\"example-box med\">B</div>\n",
999 "<div class=\"example-box lrg\">C</div>\n",
1000 "</div>"
1001 ]
1002 },
1003 {
1004 "cell_type": "heading",
1005 "level": 3,
1006 "metadata": {},
1007 "source": [
1008 "Flex classes"
1009 ]
1010 },
1011 {
1012 "cell_type": "markdown",
1013 "metadata": {},
1014 "source": [
1015 "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."
1016 ]
1017 },
1018 {
1019 "cell_type": "heading",
1020 "level": 4,
1021 "metadata": {},
1022 "source": [
1023 "Example 1"
1024 ]
1025 },
1026 {
1027 "cell_type": "markdown",
1028 "metadata": {},
1029 "source": [
912 1030 "<div class=\"example-container sm hbox center\">\n",
913 1031 "<div class=\"example-box box-flex0\">box-flex0</div>\n",
914 1032 "<div class=\"example-box box-flex0\">box-flex0</div>\n",
915 1033 "<div class=\"example-box box-flex0\">box-flex0</div>\n",
916 "</div>\n",
917 "\n",
918 "#### Example 2\n",
1034 "</div>"
1035 ]
1036 },
1037 {
1038 "cell_type": "heading",
1039 "level": 4,
1040 "metadata": {},
1041 "source": [
1042 "Example 2"
1043 ]
1044 },
1045 {
1046 "cell_type": "markdown",
1047 "metadata": {},
1048 "source": [
919 1049 "<div class=\"example-container sm hbox center\">\n",
920 1050 "<div class=\"example-box box-flex0\">box-flex0</div>\n",
921 1051 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
922 1052 "<div class=\"example-box box-flex0\">box-flex0</div>\n",
923 "</div>\n",
924 "\n",
925 "#### Example 3\n",
1053 "</div>"
1054 ]
1055 },
1056 {
1057 "cell_type": "heading",
1058 "level": 4,
1059 "metadata": {},
1060 "source": [
1061 "Example 3"
1062 ]
1063 },
1064 {
1065 "cell_type": "markdown",
1066 "metadata": {},
1067 "source": [
926 1068 "<div class=\"example-container sm hbox center\">\n",
927 1069 "<div class=\"example-box box-flex0\">box-flex0</div>\n",
928 1070 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
929 1071 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
930 "</div>\n",
931 "\n",
932 "#### Example 4\n",
1072 "</div>"
1073 ]
1074 },
1075 {
1076 "cell_type": "heading",
1077 "level": 4,
1078 "metadata": {},
1079 "source": [
1080 "Example 4"
1081 ]
1082 },
1083 {
1084 "cell_type": "markdown",
1085 "metadata": {},
1086 "source": [
933 1087 "<div class=\"example-container sm hbox center\">\n",
934 1088 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
935 1089 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
936 1090 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
937 "</div>\n",
938 "\n",
939 "#### Example 5\n",
1091 "</div>"
1092 ]
1093 },
1094 {
1095 "cell_type": "heading",
1096 "level": 4,
1097 "metadata": {},
1098 "source": [
1099 "Example 5"
1100 ]
1101 },
1102 {
1103 "cell_type": "markdown",
1104 "metadata": {},
1105 "source": [
940 1106 "<div class=\"example-container sm hbox center\">\n",
941 1107 "<div class=\"example-box box-flex2\">box-flex2</div>\n",
942 1108 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
943 1109 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
944 "</div>\n",
945 "\n",
946 "#### Example 6\n",
1110 "</div>"
1111 ]
1112 },
1113 {
1114 "cell_type": "heading",
1115 "level": 4,
1116 "metadata": {},
1117 "source": [
1118 "Example 6"
1119 ]
1120 },
1121 {
1122 "cell_type": "markdown",
1123 "metadata": {
1124 "slideshow": {
1125 "slide_type": "slide"
1126 }
1127 },
1128 "source": [
947 1129 "<div class=\"example-container sm hbox center\">\n",
948 1130 "<div class=\"example-box box-flex0\">box-flex0</div>\n",
949 1131 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
950 1132 "<div class=\"example-box box-flex2\">box-flex2</div>\n",
951 1133 "</div>"
952 1134 ]
953 1135 },
954 1136 {
955 1137 "cell_type": "heading",
956 1138 "level": 3,
957 1139 "metadata": {
958 1140 "slideshow": {
959 1141 "slide_type": "slide"
960 1142 }
961 1143 },
962 1144 "source": [
963 1145 "Application to widgets"
964 1146 ]
965 1147 },
966 1148 {
967 1149 "cell_type": "markdown",
968 1150 "metadata": {},
969 1151 "source": [
970 1152 "Widget containers **default to vbox** alignment."
971 1153 ]
972 1154 },
973 1155 {
974 1156 "cell_type": "code",
975 1157 "collapsed": false,
976 1158 "input": [
977 1159 "buttons = [widgets.ButtonWidget(description=str(i)) for i in range(3)]\n",
978 1160 "\n",
979 1161 "container = widgets.ContainerWidget(children=buttons)\n",
980 1162 "display(container)"
981 1163 ],
982 1164 "language": "python",
983 1165 "metadata": {},
984 1166 "outputs": [],
985 "prompt_number": 22
1167 "prompt_number": 29
986 1168 },
987 1169 {
988 1170 "cell_type": "heading",
989 1171 "level": 3,
990 1172 "metadata": {
991 1173 "slideshow": {
992 1174 "slide_type": "slide"
993 1175 }
994 1176 },
995 1177 "source": [
996 1178 "Using hbox"
997 1179 ]
998 1180 },
999 1181 {
1000 1182 "cell_type": "markdown",
1001 1183 "metadata": {},
1002 1184 "source": [
1003 1185 "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."
1004 1186 ]
1005 1187 },
1006 1188 {
1007 1189 "cell_type": "code",
1008 1190 "collapsed": false,
1009 1191 "input": [
1010 1192 "container = widgets.ContainerWidget(children=buttons)\n",
1011 1193 "display(container)\n",
1012 1194 "container.remove_class('vbox')\n",
1013 1195 "container.add_class('hbox')"
1014 1196 ],
1015 1197 "language": "python",
1016 1198 "metadata": {},
1017 1199 "outputs": [],
1018 "prompt_number": 23
1200 "prompt_number": 30
1019 1201 },
1020 1202 {
1021 1203 "cell_type": "markdown",
1022 1204 "metadata": {},
1023 1205 "source": [
1024 1206 "By setting the width of the container to 100% and adding the `center` class to it, you can center the buttons."
1025 1207 ]
1026 1208 },
1027 1209 {
1028 1210 "cell_type": "code",
1029 1211 "collapsed": false,
1030 1212 "input": [
1031 1213 "container.set_css('width', '100%')\n",
1032 1214 "container.add_class('center')"
1033 1215 ],
1034 1216 "language": "python",
1035 1217 "metadata": {},
1036 1218 "outputs": [],
1037 "prompt_number": 24
1219 "prompt_number": 31
1038 1220 },
1039 1221 {
1040 1222 "cell_type": "heading",
1041 1223 "level": 2,
1042 1224 "metadata": {
1043 1225 "slideshow": {
1044 1226 "slide_type": "slide"
1045 1227 }
1046 1228 },
1047 1229 "source": [
1048 1230 "Style classes"
1049 1231 ]
1050 1232 },
1051 1233 {
1052 1234 "cell_type": "markdown",
1053 1235 "metadata": {},
1054 1236 "source": [
1055 1237 "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/)."
1056 1238 ]
1057 1239 },
1058 1240 {
1059 1241 "cell_type": "heading",
1060 1242 "level": 3,
1061 1243 "metadata": {},
1062 1244 "source": [
1063 1245 "ButtonWidgets"
1064 1246 ]
1065 1247 },
1066 1248 {
1067 1249 "cell_type": "code",
1068 1250 "collapsed": false,
1069 1251 "input": [
1070 1252 "# List of the bootstrap button styles\n",
1071 1253 "classes = [\n",
1072 1254 " 'btn', \n",
1073 1255 " 'btn-primary', \n",
1074 1256 " 'btn-info', \n",
1075 1257 " 'btn-success', \n",
1076 1258 " 'btn-warning', \n",
1077 1259 " 'btn-danger', \n",
1078 1260 " 'btn-inverse', \n",
1079 1261 " 'btn-link'\n",
1080 1262 "]\n",
1081 1263 "\n",
1082 1264 "# Display the buttons in a hbox\n",
1083 1265 "container = widgets.ContainerWidget(children=[widgets.ButtonWidget(description=c) for c in classes])\n",
1084 1266 "display(container)\n",
1085 1267 "\n",
1086 1268 "# Apply classes after display\n",
1087 1269 "container.remove_class('vbox')\n",
1088 1270 "container.add_class('hbox')\n",
1089 1271 "ret = [container.children[i].add_class(c) for i, c in enumerate(classes)]"
1090 1272 ],
1091 1273 "language": "python",
1092 1274 "metadata": {},
1093 1275 "outputs": [],
1094 "prompt_number": 25
1276 "prompt_number": 32
1095 1277 },
1096 1278 {
1097 1279 "cell_type": "heading",
1098 1280 "level": 3,
1099 1281 "metadata": {
1100 1282 "slideshow": {
1101 1283 "slide_type": "slide"
1102 1284 }
1103 1285 },
1104 1286 "source": [
1105 1287 "ContainerWidgets"
1106 1288 ]
1107 1289 },
1108 1290 {
1109 1291 "cell_type": "code",
1110 1292 "collapsed": false,
1111 1293 "input": [
1112 1294 "def create_label(cls):\n",
1113 1295 " class_name = widgets.HTMLWidget(value=cls)\n",
1114 1296 " container = widgets.ContainerWidget(children=[class_name])\n",
1115 1297 " display(container)\n",
1116 1298 " container.add_class(cls)\n",
1117 1299 "\n",
1118 1300 "ret = [create_label(c) for c in [\n",
1119 1301 " 'alert', \n",
1120 1302 " 'alert alert-error', \n",
1121 1303 " 'alert alert-success', \n",
1122 1304 " 'alert alert-info'\n",
1123 1305 "]]"
1124 1306 ],
1125 1307 "language": "python",
1126 1308 "metadata": {},
1127 1309 "outputs": [],
1128 "prompt_number": 26
1310 "prompt_number": 33
1129 1311 },
1130 1312 {
1131 1313 "cell_type": "heading",
1132 1314 "level": 3,
1133 1315 "metadata": {
1134 1316 "slideshow": {
1135 1317 "slide_type": "slide"
1136 1318 }
1137 1319 },
1138 1320 "source": [
1139 1321 "ProgressWidgets"
1140 1322 ]
1141 1323 },
1142 1324 {
1143 1325 "cell_type": "code",
1144 1326 "collapsed": false,
1145 1327 "input": [
1146 1328 "classes = [\n",
1147 " 'progress-info', \n",
1148 " 'progress-success', \n",
1149 " 'progress-warning', \n",
1150 " 'progress-danger',\n",
1151 " 'progress-striped progress-info', \n",
1152 " 'progress-striped progress-success', \n",
1153 " 'progress-striped progress-warning', \n",
1154 " 'progress-striped progress-danger',\n",
1155 " 'active progress-striped progress-info', \n",
1156 " 'active progress-striped progress-success', \n",
1157 " 'active progress-striped progress-warning', \n",
1158 " 'active progress-striped progress-danger',\n",
1329 " 'progress-bar-info', \n",
1330 " 'progress-bar-success', \n",
1331 " 'progress-bar-warning', \n",
1332 " 'progress-bar-danger',\n",
1333 " 'progress-bar-info progress-striped', \n",
1334 " 'progress-bar-success progress-striped', \n",
1335 " 'progress-bar-warning progress-striped', \n",
1336 " 'progress-bar-danger progress-striped',\n",
1337 " 'active progress-bar-info progress-striped', \n",
1338 " 'active progress-bar-success progress-striped', \n",
1339 " 'active progress-bar-warning progress-striped', \n",
1340 " 'active progress-bar-danger progress-striped',\n",
1159 1341 "]\n",
1160 1342 "ws = [widgets.IntProgressWidget(value=50, description=c) for c in classes]\n",
1161 1343 "ret = [display(w) for w in ws]\n",
1162 "ret = [ws[i].add_class(c) for i, c in enumerate(classes)]"
1344 "ret = [ws[i].add_class(c, selector=\"\" if c == \"progress-striped\" or c == \"active\" else \".progress-bar\") for i, cs in enumerate(classes) for c in cs.split(' ')]"
1163 1345 ],
1164 1346 "language": "python",
1165 1347 "metadata": {},
1166 1348 "outputs": [],
1167 "prompt_number": 27
1349 "prompt_number": 48
1168 1350 },
1169 1351 {
1170 1352 "cell_type": "heading",
1171 1353 "level": 2,
1172 1354 "metadata": {
1173 1355 "slideshow": {
1174 1356 "slide_type": "slide"
1175 1357 }
1176 1358 },
1177 1359 "source": [
1178 1360 "Visibility"
1179 1361 ]
1180 1362 },
1181 1363 {
1182 1364 "cell_type": "markdown",
1183 1365 "metadata": {},
1184 1366 "source": [
1185 1367 "Sometimes it is necessary to **hide or show widgets** in place, **without having to re-display** the widget.\n",
1186 1368 "The `visibility` property of widgets can be used to hide or show **widgets that have already been displayed** (as seen below)."
1187 1369 ]
1188 1370 },
1189 1371 {
1190 1372 "cell_type": "code",
1191 1373 "collapsed": false,
1192 1374 "input": [
1193 1375 "string = widgets.LatexWidget(value=\"Hello World!\")\n",
1194 1376 "display(string) "
1195 1377 ],
1196 1378 "language": "python",
1197 1379 "metadata": {},
1198 1380 "outputs": [],
1199 "prompt_number": 28
1381 "prompt_number": 49
1200 1382 },
1201 1383 {
1202 1384 "cell_type": "code",
1203 1385 "collapsed": false,
1204 1386 "input": [
1205 1387 "string.visible=False"
1206 1388 ],
1207 1389 "language": "python",
1208 1390 "metadata": {},
1209 1391 "outputs": [],
1210 "prompt_number": 29
1392 "prompt_number": 50
1211 1393 },
1212 1394 {
1213 1395 "cell_type": "code",
1214 1396 "collapsed": false,
1215 1397 "input": [
1216 1398 "string.visible=True"
1217 1399 ],
1218 1400 "language": "python",
1219 1401 "metadata": {},
1220 1402 "outputs": [],
1221 "prompt_number": 30
1403 "prompt_number": 51
1222 1404 },
1223 1405 {
1224 1406 "cell_type": "heading",
1225 1407 "level": 3,
1226 1408 "metadata": {
1227 1409 "slideshow": {
1228 1410 "slide_type": "slide"
1229 1411 }
1230 1412 },
1231 1413 "source": [
1232 1414 "Another example"
1233 1415 ]
1234 1416 },
1235 1417 {
1236 1418 "cell_type": "markdown",
1237 1419 "metadata": {},
1238 1420 "source": [
1239 1421 "In the example below, a form is rendered, which conditionally displays widgets depending on the state of other widgets. Try toggling the student checkbox."
1240 1422 ]
1241 1423 },
1242 1424 {
1243 1425 "cell_type": "code",
1244 1426 "collapsed": false,
1245 1427 "input": [
1246 1428 "form = widgets.ContainerWidget()\n",
1247 1429 "first = widgets.TextWidget(description=\"First Name:\")\n",
1248 1430 "last = widgets.TextWidget(description=\"Last Name:\")\n",
1249 1431 "\n",
1250 1432 "student = widgets.CheckboxWidget(description=\"Student:\", value=False)\n",
1251 1433 "school_info = widgets.ContainerWidget(visible=False, children=[\n",
1252 1434 " widgets.TextWidget(description=\"School:\"),\n",
1253 1435 " widgets.IntTextWidget(description=\"Grade:\", min=0, max=12)\n",
1254 1436 " ])\n",
1255 1437 "\n",
1256 1438 "pet = widgets.TextWidget(description=\"Pet's Name:\")\n",
1257 1439 "form.children = [first, last, student, school_info, pet]\n",
1258 1440 "display(form)\n",
1259 1441 "\n",
1260 1442 "def on_student_toggle(name, value):\n",
1261 1443 " if value:\n",
1262 1444 " school_info.visible = True\n",
1263 1445 " else:\n",
1264 1446 " school_info.visible = False\n",
1265 1447 "student.on_trait_change(on_student_toggle, 'value')\n"
1266 1448 ],
1267 1449 "language": "python",
1268 1450 "metadata": {},
1269 1451 "outputs": [],
1270 "prompt_number": 31
1452 "prompt_number": 52
1271 1453 },
1272 1454 {
1273 1455 "cell_type": "markdown",
1274 1456 "metadata": {},
1275 1457 "source": [
1276 1458 "[Index](Index.ipynb) - [Back](Widget Events.ipynb) - [Next](Custom Widget - Hello World.ipynb)"
1277 1459 ]
1278 1460 }
1279 1461 ],
1280 1462 "metadata": {}
1281 1463 }
1282 1464 ]
1283 1465 } No newline at end of file
@@ -1,279 +1,254 b''
1 1 {
2 2 "metadata": {
3 3 "name": "",
4 "signature": "sha256:9888adccfb9af4c96f19c546d32e6177a811d297c52a97c23a84e67b355cbff0"
4 "signature": "sha256:1a6a6a01ea6dbb9b101174c11ba522cb145e4a070685a43a71b5ccdb75672909"
5 5 },
6 6 "nbformat": 3,
7 7 "nbformat_minor": 0,
8 8 "worksheets": [
9 9 {
10 10 "cells": [
11 11 {
12 12 "cell_type": "heading",
13 13 "level": 1,
14 14 "metadata": {},
15 15 "source": [
16 16 "Notebook Basics"
17 17 ]
18 18 },
19 19 {
20 20 "cell_type": "markdown",
21 21 "metadata": {},
22 22 "source": [
23 23 "This notebook assumes that you already have IPython [installed](http://ipython.org/install.html) and are able to start the notebook server by running:\n",
24 24 "\n",
25 25 " ipython notebook\n",
26 26 "\n",
27 27 "For more details on how to run the notebook server, see [Running the Notebook Server](Running the Notebook Server.ipynb)."
28 28 ]
29 29 },
30 30 {
31 31 "cell_type": "heading",
32 32 "level": 2,
33 33 "metadata": {},
34 34 "source": [
35 35 "The Notebook dashboard"
36 36 ]
37 37 },
38 38 {
39 39 "cell_type": "markdown",
40 40 "metadata": {},
41 41 "source": [
42 42 "When you first start the notebook server, your browser will open to the notebook dashboard. The dashboard serves as a home page for the notebook. Its main purpose is to display the notebooks in the current directory. For example, here is a screenshot of the dashboard page for the `examples` directory in the IPython repository:\n",
43 43 "\n",
44 44 "<img src=\"images/dashboard_notebooks_tab.png\" />\n",
45 45 "\n",
46 46 "The top of the notebook list displays clickable breadcrumbs of the current directory. By clicking on these breadcrumbs or on sub-directories in the notebook list, you can navigate your file system.\n",
47 47 "\n",
48 48 "To create a new notebook, click on the \"New Notebook\" button at the top of the list.\n",
49 49 "\n",
50 50 "Notebooks can be uploaded to the current directory by dragging a notebook file onto the notebook list or by the \"click here\" text above the list.\n",
51 51 "\n",
52 52 "The notebook list shows a red \"Shutdown\" button for running notebooks and a \"Delete\" button for stopped notebooks. Notebook remain running until you explicitly click the \"Shutdown\" button; closing the notebook's page is not sufficient.\n",
53 53 "\n",
54 54 "To see all of your running notebooks along with their directories, click on the \"Running\" tab:\n",
55 55 "\n",
56 56 "<img src=\"images/dashboard_running_tab.png\" />\n",
57 57 "\n",
58 58 "This view provides a convenient way to track notebooks that you start as you navigate the file system in a long running notebook server."
59 59 ]
60 60 },
61 61 {
62 62 "cell_type": "heading",
63 63 "level": 2,
64 64 "metadata": {},
65 65 "source": [
66 66 "Overview of the Notebook UI"
67 67 ]
68 68 },
69 69 {
70 70 "cell_type": "markdown",
71 71 "metadata": {},
72 72 "source": [
73 73 "<div class=\"alert\">\n",
74 74 "As of IPython 2.0, the user interface has changed significantly. Because of this we highly recommend existing users to review this information after upgrading to IPython 2.0. All new users of IPython should review this information as well.\n",
75 75 "</div>"
76 76 ]
77 77 },
78 78 {
79 79 "cell_type": "markdown",
80 80 "metadata": {},
81 81 "source": [
82 82 "If you create a new notebook or open an existing one, you will be taken to the notebook user interface (UI). This UI allows you to run code and author notebook documents interactively. The notebook UI has the following main areas:\n",
83 83 "\n",
84 84 "* Menu\n",
85 85 "* Toolbar\n",
86 86 "* Notebook area and cells\n",
87 87 "\n",
88 88 "IPython 2.0 has an interactive tour of these elements that can be started in the \"Help:User Interface Tour\" menu item."
89 89 ]
90 90 },
91 91 {
92 92 "cell_type": "heading",
93 93 "level": 2,
94 94 "metadata": {},
95 95 "source": [
96 96 "Modal editor"
97 97 ]
98 98 },
99 99 {
100 100 "cell_type": "markdown",
101 101 "metadata": {},
102 102 "source": [
103 103 "Starting with IPython 2.0, the IPython Notebook has a modal user interface. This means that the keyboard does different things depending on which mode the Notebook is in. There are two modes: edit mode and command mode."
104 104 ]
105 105 },
106 106 {
107 107 "cell_type": "heading",
108 108 "level": 3,
109 109 "metadata": {},
110 110 "source": [
111 111 "Edit mode"
112 112 ]
113 113 },
114 114 {
115 115 "cell_type": "markdown",
116 116 "metadata": {},
117 117 "source": [
118 118 "Edit mode is indicated by a green cell border and a prompt showing in the editor area:\n",
119 119 "\n",
120 120 "<img src=\"images/edit_mode.png\">\n",
121 121 "\n",
122 122 "When a cell is in edit mode, you can type into the cell, like a normal text editor."
123 123 ]
124 124 },
125 125 {
126 126 "cell_type": "markdown",
127 127 "metadata": {},
128 128 "source": [
129 129 "<div class=\"alert alert-success\">\n",
130 130 "Enter edit mode by pressing `Enter` or using the mouse to click on a cell's editor area.\n",
131 131 "</div>"
132 132 ]
133 133 },
134 134 {
135 135 "cell_type": "heading",
136 136 "level": 3,
137 137 "metadata": {},
138 138 "source": [
139 139 "Command mode"
140 140 ]
141 141 },
142 142 {
143 143 "cell_type": "markdown",
144 144 "metadata": {},
145 145 "source": [
146 146 "Command mode is indicated by a grey cell border:\n",
147 147 "\n",
148 148 "<img src=\"images/command_mode.png\">\n",
149 149 "\n",
150 150 "When you are in command mode, you are able to edit the notebook as a whole, but not type into individual cells. Most importantly, in command mode, the keyboard is mapped to a set of shortcuts that let you perform notebook and cell actions efficiently. For example, if you are in command mode and you press `c`, you will copy the current cell - no modifier is needed."
151 151 ]
152 152 },
153 153 {
154 154 "cell_type": "markdown",
155 155 "metadata": {},
156 156 "source": [
157 157 "<div class=\"alert alert-error\">\n",
158 158 "Don't try to type into a cell in command mode; unexpected things will happen!\n",
159 159 "</div>"
160 160 ]
161 161 },
162 162 {
163 163 "cell_type": "markdown",
164 164 "metadata": {},
165 165 "source": [
166 166 "<div class=\"alert alert-success\">\n",
167 167 "Enter command mode by pressing `Esc` or using the mouse to click *outside* a cell's editor area.\n",
168 168 "</div>"
169 169 ]
170 170 },
171 171 {
172 172 "cell_type": "heading",
173 173 "level": 2,
174 174 "metadata": {},
175 175 "source": [
176 176 "Mouse navigation"
177 177 ]
178 178 },
179 179 {
180 180 "cell_type": "markdown",
181 181 "metadata": {},
182 182 "source": [
183 183 "All navigation and actions in the Notebook are available using the mouse through the menubar and toolbar, which are both above the main Notebook area:\n",
184 184 "\n",
185 185 "<img src=\"images/menubar_toolbar.png\">"
186 186 ]
187 187 },
188 188 {
189 189 "cell_type": "markdown",
190 190 "metadata": {},
191 191 "source": [
192 192 "The first idea of mouse based navigation is that **cells can be selected by clicking on them.** The currently selected cell gets a grey or green border depending on whether the notebook is in edit or command mode. If you click inside a cell's editor area, you will enter edit mode. If you click on the prompt or output area of a cell you will enter command mode.\n",
193 193 "\n",
194 194 "If you are running this notebook in a live session (not on http://nbviewer.ipython.org) try selecting different cells and going between edit and command mode. Try typing into a cell."
195 195 ]
196 196 },
197 197 {
198 198 "cell_type": "markdown",
199 199 "metadata": {},
200 200 "source": [
201 201 "The second idea of mouse based navigation is that **cell actions usually apply to the currently selected cell**. Thus if you want to run the code in a cell, you would select it and click the <button><i class=\"icon-play\"></i></button> button in the toolbar or the \"Cell:Run\" menu item. Similarly, to copy a cell you would select it and click the <button><i class=\"icon-copy\"></i></button> button in the toolbar or the \"Edit:Copy\" menu item. With this simple pattern, you should be able to do most everything you need with the mouse.\n",
202 202 "\n",
203 203 "Markdown and heading cells have one other state that can be modified with the mouse. These cells can either be rendered or unrendered. When they are rendered, you will see a nice formatted representation of the cell's contents. When they are unrendered, you will see the raw text source of the cell. To render the selected cell with the mouse, click the <button><i class=\"icon-play\"></i></button> button in the toolbar or the \"Cell:Run\" menu item. To unrender the selected cell, double click on the cell."
204 204 ]
205 205 },
206 206 {
207 207 "cell_type": "heading",
208 208 "level": 2,
209 209 "metadata": {},
210 210 "source": [
211 211 "Keyboard Navigation"
212 212 ]
213 213 },
214 214 {
215 215 "cell_type": "markdown",
216 216 "metadata": {},
217 217 "source": [
218 218 "The modal user interface of the IPython Notebook has been optimized for efficient keyboard usage. This is made possible by having two different sets of keyboard shortcuts: one set that is active in edit mode and another in command mode.\n",
219 219 "\n",
220 220 "The most important keyboard shortcuts are `Enter`, which enters edit mode, and `Esc`, which enters command mode.\n",
221 221 "\n",
222 222 "In edit mode, most of the keyboard is dedicated to typing into the cell's editor. Thus, in edit mode there are relatively few shortcuts:\n",
223 223 "\n",
224 224 "<img src=\"images/edit_shortcuts.png\">"
225 225 ]
226 226 },
227 227 {
228 228 "cell_type": "markdown",
229 229 "metadata": {},
230 230 "source": [
231 231 "In command mode, the entire keyboard is available for shortcuts, so there are many more:\n",
232 232 "\n",
233 233 "<img src=\"images/command_shortcuts.png\">"
234 234 ]
235 235 },
236 236 {
237 237 "cell_type": "markdown",
238 238 "metadata": {},
239 239 "source": [
240 240 "We recommend learning the command mode shortcuts in the following rough order:\n",
241 241 "\n",
242 242 "1. Basic navigation: `enter`, `shift-enter`, `up/k`, `down/j`\n",
243 243 "2. Saving the notebook: `s`\n",
244 244 "2. Cell types: `y`, `m`, `1-6`, `t`\n",
245 245 "3. Cell creation and movement: `a`, `b`, `ctrl+k`, `ctrl+j`\n",
246 246 "4. Cell editing: `x`, `c`, `v`, `d`, `z`, `shift+=`\n",
247 247 "5. Kernel operations: `i`, `.`"
248 248 ]
249 },
250 {
251 "cell_type": "heading",
252 "level": 2,
253 "metadata": {},
254 "source": [
255 "Cell types"
256 ]
257 },
258 {
259 "cell_type": "markdown",
260 "metadata": {},
261 "source": [
262 "The notebook UI and notebook documents are a linear sequence of cells. There are four cell types:\n",
263 "\n",
264 "* **Code cells:** Input and output of live code that is run in the kernel\n",
265 "* **Markdown cells:** Narrative text with embedded LaTeX equations\n",
266 "* **Heading cells:** 6 levels of hierarchical organization and formatting\n",
267 "* **Raw cells:** Unformatted text that is included, without modification, when notebooks are converted to different formats using nbconvert\n",
268 "\n",
269 "More information about running code and Markdown cells can be found in these tutorials:\n",
270 "\n",
271 "* [Running Code](Running Code.ipynb)\n",
272 "* [Working With Markdown Cells](Working With Markdown Cells.ipynb)"
273 ]
274 249 }
275 250 ],
276 251 "metadata": {}
277 252 }
278 253 ]
279 254 } No newline at end of file
@@ -1,129 +1,180 b''
1 1 {
2 2 "metadata": {
3 "celltoolbar": "Slideshow",
3 4 "name": "",
4 "signature": "sha256:1fd1c67d342de34c5edf43789ce56f80963eda3662752e7d9cbc97ac54848be8"
5 "signature": "sha256:ad9cb95b14212dbf9fc8ecafa475d0e368e4cb7c7306b89628b500e7e40068b6"
5 6 },
6 7 "nbformat": 3,
7 8 "nbformat_minor": 0,
8 9 "worksheets": [
9 10 {
10 11 "cells": [
11 12 {
12 13 "cell_type": "heading",
13 14 "level": 1,
14 "metadata": {},
15 "metadata": {
16 "slideshow": {
17 "slide_type": "slide"
18 }
19 },
15 20 "source": [
16 21 "What is the IPython Notebook?"
17 22 ]
18 23 },
19 24 {
20 25 "cell_type": "heading",
21 26 "level": 2,
22 27 "metadata": {},
23 28 "source": [
24 29 "Introduction"
25 30 ]
26 31 },
27 32 {
28 33 "cell_type": "markdown",
29 34 "metadata": {},
30 35 "source": [
31 "The IPython Notebook is an interactive computing environment that enables users to author notebook documents that include live code, interactive widgets, plots, narrative text, equations, images and video. These documents provide a complete and self-contained record of a computation that can be converted to various formats and shared with others using email, [Dropbox](http://dropbox.com), version control systems (like git/[GitHub](http://github.com)) or [nbviewer.ipython.org](http://nbviewer.ipython.org).\n",
32 "\n",
33 "Through IPython's kernel and messaging architecture, the Notebook allows code to be run in a range of different programming languages, including Python, R, Julia, Ruby and many others.\n",
36 "The IPython Notebook is an **interactive computing environment** that enables users to author notebook documents that include: \n",
37 "- Live code\n",
38 "- Interactive widgets\n",
39 "- Plots\n",
40 "- Narrative text\n",
41 "- Equations\n",
42 "- Images\n",
43 "- Video\n",
34 44 "\n",
45 "These documents provide a **complete and self-contained record of a computation** that can be converted to various formats and shared with others using email, [Dropbox](http://dropbox.com), version control systems (like git/[GitHub](http://github.com)) or [nbviewer.ipython.org](http://nbviewer.ipython.org)."
46 ]
47 },
48 {
49 "cell_type": "heading",
50 "level": 3,
51 "metadata": {
52 "slideshow": {
53 "slide_type": "slide"
54 }
55 },
56 "source": [
57 "Components"
58 ]
59 },
60 {
61 "cell_type": "markdown",
62 "metadata": {},
63 "source": [
35 64 "The IPython Notebook combines three components:\n",
36 65 "\n",
37 66 "* **The notebook web application**: An interactive web application for writing and running code interactively and authoring notebook documents.\n",
38 67 "* **Kernels**: Separate processes started by the notebook web application that runs users' code in a given language and returns output back to the notebook web application. The kernel also handles things like computations for interactive widgets, tab completion and introspection. \n",
39 68 "* **Notebook documents**: Self-contained documents that contain a representation of all content visible in the notebook web application, including inputs and outputs of the computations, narrative\n",
40 69 "text, equations, images, and rich media representations of objects. Each notebook document has its own kernel."
41 70 ]
42 71 },
43 72 {
44 73 "cell_type": "heading",
45 74 "level": 2,
46 "metadata": {},
75 "metadata": {
76 "slideshow": {
77 "slide_type": "slide"
78 }
79 },
47 80 "source": [
48 81 "Notebook web application"
49 82 ]
50 83 },
51 84 {
52 85 "cell_type": "markdown",
53 86 "metadata": {},
54 87 "source": [
55 88 "The notebook web application enables users to:\n",
56 89 "\n",
57 "* Edit code in the browser, with automatic syntax highlighting, indentation, and tab completion/introspection.\n",
58 "* Run code from the browser, with the results of computations attached to the code which generated them.\n",
59 "* See the results of computations with rich media representations, such as HTML, LaTeX, PNG, SVG, PDF, etc.\n",
60 "* Create and use interactive JavaScript wigets, which bind interactive user interface controls and visualizations to reactive kernel side computations.\n",
61 "* Author narrative text using the [Markdown](https://daringfireball.net/projects/markdown/) markup language.\n",
62 "* Build hierarchical documents that are organized into sections with different levels of headings.\n",
63 "* Include mathematical equations using LaTeX syntax in Markdown, which are rendered in-browser by [MathJax](http://www.mathjax.org/).\n",
64 "* Start parallel computing clusters that work with IPython's interactive parallel computing libraries `IPython.parallel`."
90 "* **Edit code in the browser**, with automatic syntax highlighting, indentation, and tab completion/introspection.\n",
91 "* **Run code from the browser**, with the results of computations attached to the code which generated them.\n",
92 "* See the results of computations with **rich media representations**, such as HTML, LaTeX, PNG, SVG, PDF, etc.\n",
93 "* Create and use **interactive JavaScript wigets**, which bind interactive user interface controls and visualizations to reactive kernel side computations.\n",
94 "* Author **narrative text** using the [Markdown](https://daringfireball.net/projects/markdown/) markup language.\n",
95 "* Build **hierarchical documents** that are organized into sections with different levels of headings.\n",
96 "* Include mathematical equations using **LaTeX syntax in Markdown**, which are rendered in-browser by [MathJax](http://www.mathjax.org/).\n",
97 "* Start **parallel computing** clusters that work with IPython's interactive parallel computing libraries `IPython.parallel`."
65 98 ]
66 99 },
67 100 {
68 101 "cell_type": "heading",
69 102 "level": 2,
70 "metadata": {},
103 "metadata": {
104 "slideshow": {
105 "slide_type": "slide"
106 }
107 },
71 108 "source": [
72 109 "Kernels"
73 110 ]
74 111 },
75 112 {
76 113 "cell_type": "markdown",
77 114 "metadata": {},
78 115 "source": [
79 "For each notebook document that a user opens, the web application starts a kernel that runs the code for that notebook. Each kernel is capable of running code in a single programming language and there are kernels available in the following languages:\n",
116 "Through IPython's kernel and messaging architecture, the Notebook allows code to be run in a range of different programming languages. For each notebook document that a user opens, the web application starts a kernel that runs the code for that notebook. Each kernel is capable of running code in a single programming language and there are kernels available in the following languages:\n",
80 117 "\n",
81 118 "* Python(https://github.com/ipython/ipython)\n",
82 119 "* Julia (https://github.com/JuliaLang/IJulia.jl)\n",
83 120 "* R (https://github.com/takluyver/IRkernel)\n",
84 121 "* Ruby (https://github.com/minrk/iruby)\n",
85 122 "* Haskell (https://github.com/gibiansky/IHaskell)\n",
86 123 "* Scala (https://github.com/Bridgewater/scala-notebook)\n",
87 124 "* node.js (https://gist.github.com/Carreau/4279371)\n",
88 125 "* Go (https://github.com/takluyver/igo)\n",
89 126 "\n",
90 127 "The default kernel runs Python code. When it is released in the Summer/Fall of 2014, IPython 3.0 will provide a simple way for users to pick which of these kernels is used for a given notebook. \n",
91 128 "\n",
92 129 "Each of these kernels communicate with the notebook web application and web browser using a JSON over ZeroMQ/WebSockets message protocol that is described [here](http://ipython.org/ipython-doc/dev/development/messaging.html). Most users don't need to know about these details, but it helps to understand that \"kernels run code.\""
93 130 ]
94 131 },
95 132 {
96 133 "cell_type": "heading",
97 134 "level": 2,
98 "metadata": {},
135 "metadata": {
136 "slideshow": {
137 "slide_type": "slide"
138 }
139 },
99 140 "source": [
100 141 "Notebook documents"
101 142 ]
102 143 },
103 144 {
104 145 "cell_type": "markdown",
105 146 "metadata": {},
106 147 "source": [
107 "Notebook documents contain the inputs and outputs of an interactive session as well as narrative text that accompanies the code but is not meant for execution. Rich output generated by running code, including HTML, images, video, and plots, is embeddeed in the notebook, which makes it a complete and self-contained record of a computation. \n",
108 "\n",
109 "When you run the notebook web application on your computer, notebook documents are just files on your local filesystem with a `.ipynb` extension. This allows you to use familiar workflows for organizing your notebooks into folders and sharing them with others using email, Dropbox and version control systems.\n",
110 "\n",
111 "Notebooks consist of a linear sequence of cells. There are four basic cell types:\n",
148 "Notebook documents contain the **inputs and outputs** of an interactive session as well as **narrative text** that accompanies the code but is not meant for execution. **Rich output** generated by running code, including HTML, images, video, and plots, is embeddeed in the notebook, which makes it a complete and self-contained record of a computation. "
149 ]
150 },
151 {
152 "cell_type": "markdown",
153 "metadata": {},
154 "source": [
155 "When you run the notebook web application on your computer, notebook documents are just **files on your local filesystem with a `.ipynb` extension**. This allows you to use familiar workflows for organizing your notebooks into folders and sharing them with others using email, Dropbox and version control systems."
156 ]
157 },
158 {
159 "cell_type": "markdown",
160 "metadata": {},
161 "source": [
162 "Notebooks consist of a **linear sequence of cells**. There are four basic cell types:\n",
112 163 "\n",
113 164 "* **Code cells:** Input and output of live code that is run in the kernel\n",
114 165 "* **Markdown cells:** Narrative text with embedded LaTeX equations\n",
115 166 "* **Heading cells:** 6 levels of hierarchical organization and formatting\n",
116 167 "* **Raw cells:** Unformatted text that is included, without modification, when notebooks are converted to different formats using nbconvert\n",
117 168 "\n",
118 "Internally, notebook documents are [JSON](http://en.wikipedia.org/wiki/JSO) data with binary values [base64](http://en.wikipedia.org/wiki/Base64) encoded. This allows them to be read and manipulated programmatically by any programming language. Because JSON is a text format, notebook documents are version control friendly.\n",
169 "Internally, notebook documents are **[JSON](http://en.wikipedia.org/wiki/JSO) data** with **binary values [base64]**(http://en.wikipedia.org/wiki/Base64) encoded. This allows them to be **read and manipulated programmatically** by any programming language. Because JSON is a text format, notebook documents are version control friendly.\n",
119 170 "\n",
120 "Notebooks can be exported to different static formats including HTML, reStructeredText, LaTeX, PDF, and slide shows ([reveal.js](http://lab.hakim.se/reveal-js/#/)) using IPython's `nbconvert` utility.\n",
171 "**Notebooks can be exported** to different static formats including HTML, reStructeredText, LaTeX, PDF, and slide shows ([reveal.js](http://lab.hakim.se/reveal-js/#/)) using IPython's `nbconvert` utility.\n",
121 172 "\n",
122 "Furthermore, any notebook document available from a public URL on or GitHub can be shared via http://nbviewer.ipython.org. This service loads the notebook document from the URL and renders it as a static web page. The resulting web page may thus be shared with others without their needing to install IPython."
173 "Furthermore, any notebook document available from a **public URL on or GitHub can be shared** via http://nbviewer.ipython.org. This service loads the notebook document from the URL and renders it as a static web page. The resulting web page may thus be shared with others **without their needing to install IPython**."
123 174 ]
124 175 }
125 176 ],
126 177 "metadata": {}
127 178 }
128 179 ]
129 180 } No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now