##// END OF EJS Templates
Widget styling updates for pydata2014
Jonathan Frederic -
Show More
This diff has been collapsed as it changes many lines, (1056 lines changed) Show them Hide them
@@ -7,7 +7,7 b''
7 7 ]
8 8 ],
9 9 "name": "",
10 "signature": "sha256:cd7d3d42126bdbf20c087014460779dfbdb0a63dcb8f489ba7ebfc230a685edd"
10 "signature": "sha256:55ee4a4661f0939c40550752218a4c127b985536811190a2b7e581d7fe25cec7"
11 11 },
12 12 "nbformat": 3,
13 13 "nbformat_minor": 0,
@@ -18,243 +18,865 b''
18 18 "cell_type": "code",
19 19 "collapsed": false,
20 20 "input": [
21 "from IPython.html import widgets # Widget definitions\n",
22 "from IPython.display import display # Used to display widgets in the notebook"
21 "%%html\n",
22 "<style>\n",
23 ".example-container { background: #999999; padding: 2px; min-height: 100px; }\n",
24 ".example-container.sm { min-height: 50px; }\n",
25 ".example-box { background: #9999FF; width: 50px; height: 50px; text-align: center; vertical-align: middle; color: white; font-weight: bold; margin: 2px;}\n",
26 ".example-box.med { width: 65px; height: 65px; } \n",
27 ".example-box.lrg { width: 80px; height: 80px; } \n",
28 "</style>"
29 ],
30 "language": "python",
31 "metadata": {},
32 "outputs": [
33 {
34 "html": [
35 "<style>\n",
36 ".example-container { background: #999999; padding: 2px; min-height: 100px; }\n",
37 ".example-container.sm { min-height: 50px; }\n",
38 ".example-box { background: #9999FF; width: 50px; height: 50px; text-align: center; vertical-align: middle; color: white; font-weight: bold; margin: 2px;}\n",
39 ".example-box.med { width: 65px; height: 65px; } \n",
40 ".example-box.lrg { width: 80px; height: 80px; } \n",
41 "</style>"
42 ],
43 "metadata": {},
44 "output_type": "display_data",
45 "text": [
46 "<IPython.core.display.HTML object>"
47 ]
48 }
49 ],
50 "prompt_number": 145
51 },
52 {
53 "cell_type": "heading",
54 "level": 1,
55 "metadata": {},
56 "source": [
57 "CSS"
58 ]
59 },
60 {
61 "cell_type": "markdown",
62 "metadata": {},
63 "source": [
64 "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`."
65 ]
66 },
67 {
68 "cell_type": "code",
69 "collapsed": false,
70 "input": [
71 "from IPython.html import widgets\n",
72 "text = widgets.TextWidget()\n",
73 "text.set_css('background', 'lime')\n",
74 "text "
75 ],
76 "language": "python",
77 "metadata": {},
78 "outputs": [],
79 "prompt_number": 146
80 },
81 {
82 "cell_type": "markdown",
83 "metadata": {},
84 "source": [
85 "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. The following example sets the `TextWidget`'s background to blue."
86 ]
87 },
88 {
89 "cell_type": "code",
90 "collapsed": false,
91 "input": [
92 "text.set_css('background', '#0000FF')"
93 ],
94 "language": "python",
95 "metadata": {},
96 "outputs": [],
97 "prompt_number": 147
98 },
99 {
100 "cell_type": "markdown",
101 "metadata": {},
102 "source": [
103 "Font color is just `color`."
104 ]
105 },
106 {
107 "cell_type": "code",
108 "collapsed": false,
109 "input": [
110 "text.set_css('color', '#FFFFFF')"
111 ],
112 "language": "python",
113 "metadata": {},
114 "outputs": [],
115 "prompt_number": 148
116 },
117 {
118 "cell_type": "markdown",
119 "metadata": {},
120 "source": [
121 "To remove the styling, you can call `set_css` again, but use an empty string instead of a color value."
122 ]
123 },
124 {
125 "cell_type": "code",
126 "collapsed": false,
127 "input": [
128 "text.set_css('background', '')"
129 ],
130 "language": "python",
131 "metadata": {},
132 "outputs": [],
133 "prompt_number": 149
134 },
135 {
136 "cell_type": "markdown",
137 "metadata": {},
138 "source": [
139 "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)."
140 ]
141 },
142 {
143 "cell_type": "code",
144 "collapsed": false,
145 "input": [
146 "btn = widgets.ButtonWidget()\n",
147 "btn.set_css({\n",
148 " 'width': '100px',\n",
149 " 'height': '100px',\n",
150 "})\n",
151 "btn"
152 ],
153 "language": "python",
154 "metadata": {},
155 "outputs": [],
156 "prompt_number": 150
157 },
158 {
159 "cell_type": "markdown",
160 "metadata": {},
161 "source": [
162 "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"
163 ]
164 },
165 {
166 "cell_type": "heading",
167 "level": 1,
168 "metadata": {},
169 "source": [
170 "Parent/Child Relationships"
171 ]
172 },
173 {
174 "cell_type": "markdown",
175 "metadata": {},
176 "source": [
177 "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. In other words, *widget A* cannot have *widget B* listed twice in it's list of children.\n",
178 "\n",
179 "Widgets that can contain other widgets have a `children` attribute. This attribute can be set via a kwarg in the widget's constructor or after construction. Calling display on an object with children automatically displays those children, too."
180 ]
181 },
182 {
183 "cell_type": "code",
184 "collapsed": false,
185 "input": [
186 "\n",
187 "from IPython.display import display\n",
188 "\n",
189 "float_range = widgets.FloatSliderWidget()\n",
190 "string = widgets.TextWidget(value='hi')\n",
191 "container = widgets.ContainerWidget(children=[float_range, string])\n",
192 "\n",
193 "container.set_css('border', '3px dotted red')\n",
194 "display(container) # Displays the `container` and all of it's children."
195 ],
196 "language": "python",
197 "metadata": {},
198 "outputs": [],
199 "prompt_number": 151
200 },
201 {
202 "cell_type": "markdown",
203 "metadata": {},
204 "source": [
205 "Children can also be added to parents after the parent has been displayed. The parent is responsible for rendering its children."
206 ]
207 },
208 {
209 "cell_type": "code",
210 "collapsed": false,
211 "input": [
212 "container = widgets.ContainerWidget()\n",
213 "container.set_css('border', '3px dotted red')\n",
214 "display(container)\n",
215 "\n",
216 "int_range = widgets.IntSliderWidget()\n",
217 "container.children=[int_range]"
218 ],
219 "language": "python",
220 "metadata": {},
221 "outputs": [],
222 "prompt_number": 152
223 },
224 {
225 "cell_type": "heading",
226 "level": 2,
227 "metadata": {},
228 "source": [
229 "Fancy containers"
230 ]
231 },
232 {
233 "cell_type": "markdown",
234 "metadata": {},
235 "source": [
236 "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."
237 ]
238 },
239 {
240 "cell_type": "heading",
241 "level": 3,
242 "metadata": {},
243 "source": [
244 "AccordionWidget"
245 ]
246 },
247 {
248 "cell_type": "code",
249 "collapsed": false,
250 "input": [
251 "name1 = widgets.TextWidget(description='Location:')\n",
252 "zip1 = widgets.BoundedIntTextWidget(description='Zip:', min=0, max=99999)\n",
253 "page1 = widgets.ContainerWidget(children=[name1, zip1])\n",
254 "\n",
255 "name2 = widgets.TextWidget(description='Location:')\n",
256 "zip2 = widgets.BoundedIntTextWidget(description='Zip:', min=0, max=99999)\n",
257 "page2 = widgets.ContainerWidget(children=[name2, zip2])\n",
258 "\n",
259 "accord = widgets.AccordionWidget(children=[page1, page2])\n",
260 "display(accord)\n",
261 "\n",
262 "accord.set_title(0, 'From')\n",
263 "accord.set_title(1, 'To')"
264 ],
265 "language": "python",
266 "metadata": {},
267 "outputs": [],
268 "prompt_number": 153
269 },
270 {
271 "cell_type": "heading",
272 "level": 3,
273 "metadata": {},
274 "source": [
275 "TabWidget"
276 ]
277 },
278 {
279 "cell_type": "code",
280 "collapsed": false,
281 "input": [
282 "name = widgets.TextWidget(description='Name:')\n",
283 "color = widgets.DropdownWidget(description='Color:', values=['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'])\n",
284 "page1 = widgets.ContainerWidget(children=[name, color])\n",
285 "\n",
286 "age = widgets.IntSliderWidget(description='Age:', min=0, max=120, value=50)\n",
287 "gender = widgets.RadioButtonsWidget(description='Gender:', values=['male', 'female'])\n",
288 "page2 = widgets.ContainerWidget(children=[age, gender])\n",
289 "\n",
290 "tabs = widgets.TabWidget(children=[page1, page2])\n",
291 "display(tabs)\n",
292 "\n",
293 "tabs.set_title(0, 'Name')\n",
294 "tabs.set_title(1, 'Details')"
295 ],
296 "language": "python",
297 "metadata": {},
298 "outputs": [],
299 "prompt_number": 154
300 },
301 {
302 "cell_type": "heading",
303 "level": 3,
304 "metadata": {},
305 "source": [
306 "PopupWidget"
307 ]
308 },
309 {
310 "cell_type": "markdown",
311 "metadata": {},
312 "source": [
313 "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. "
314 ]
315 },
316 {
317 "cell_type": "code",
318 "collapsed": false,
319 "input": [
320 "counter = widgets.IntTextWidget(description='Counter:')\n",
321 "popup = widgets.PopupWidget(children=[counter], description='Popup Demo', button_text='Popup Button')\n",
322 "display(popup)"
323 ],
324 "language": "python",
325 "metadata": {},
326 "outputs": [],
327 "prompt_number": 155
328 },
329 {
330 "cell_type": "code",
331 "collapsed": false,
332 "input": [
333 "counter.value += 1"
334 ],
335 "language": "python",
336 "metadata": {},
337 "outputs": [],
338 "prompt_number": 156
339 },
340 {
341 "cell_type": "code",
342 "collapsed": false,
343 "input": [],
344 "language": "python",
345 "metadata": {},
346 "outputs": [],
347 "prompt_number": 156
348 },
349 {
350 "cell_type": "code",
351 "collapsed": false,
352 "input": [],
353 "language": "python",
354 "metadata": {},
355 "outputs": [],
356 "prompt_number": 156
357 },
358 {
359 "cell_type": "code",
360 "collapsed": false,
361 "input": [],
362 "language": "python",
363 "metadata": {},
364 "outputs": [],
365 "prompt_number": 156
366 },
367 {
368 "cell_type": "code",
369 "collapsed": false,
370 "input": [],
371 "language": "python",
372 "metadata": {},
373 "outputs": [],
374 "prompt_number": 156
375 },
376 {
377 "cell_type": "code",
378 "collapsed": false,
379 "input": [],
380 "language": "python",
381 "metadata": {},
382 "outputs": [],
383 "prompt_number": 156
384 },
385 {
386 "cell_type": "code",
387 "collapsed": false,
388 "input": [],
389 "language": "python",
390 "metadata": {},
391 "outputs": [],
392 "prompt_number": 156
393 },
394 {
395 "cell_type": "code",
396 "collapsed": false,
397 "input": [],
398 "language": "python",
399 "metadata": {},
400 "outputs": [],
401 "prompt_number": 156
402 },
403 {
404 "cell_type": "code",
405 "collapsed": false,
406 "input": [],
407 "language": "python",
408 "metadata": {},
409 "outputs": [],
410 "prompt_number": 156
411 },
412 {
413 "cell_type": "code",
414 "collapsed": false,
415 "input": [],
416 "language": "python",
417 "metadata": {},
418 "outputs": [],
419 "prompt_number": 156
420 },
421 {
422 "cell_type": "code",
423 "collapsed": false,
424 "input": [],
425 "language": "python",
426 "metadata": {},
427 "outputs": [],
428 "prompt_number": 156
429 },
430 {
431 "cell_type": "code",
432 "collapsed": false,
433 "input": [],
434 "language": "python",
435 "metadata": {},
436 "outputs": [],
437 "prompt_number": 156
438 },
439 {
440 "cell_type": "code",
441 "collapsed": false,
442 "input": [],
443 "language": "python",
444 "metadata": {},
445 "outputs": [],
446 "prompt_number": 156
447 },
448 {
449 "cell_type": "code",
450 "collapsed": false,
451 "input": [],
452 "language": "python",
453 "metadata": {},
454 "outputs": [],
455 "prompt_number": 156
456 },
457 {
458 "cell_type": "code",
459 "collapsed": false,
460 "input": [],
461 "language": "python",
462 "metadata": {},
463 "outputs": [],
464 "prompt_number": 156
465 },
466 {
467 "cell_type": "code",
468 "collapsed": false,
469 "input": [
470 "counter.value += 1"
471 ],
472 "language": "python",
473 "metadata": {},
474 "outputs": [],
475 "prompt_number": 157
476 },
477 {
478 "cell_type": "code",
479 "collapsed": false,
480 "input": [
481 "popup.close()"
23 482 ],
24 483 "language": "python",
25 484 "metadata": {},
26 485 "outputs": [],
27 "prompt_number": 1
486 "prompt_number": 158
28 487 },
29 488 {
30 489 "cell_type": "heading",
31 490 "level": 1,
32 491 "metadata": {},
33 492 "source": [
34 "CSS"
493 "Alignment"
35 494 ]
36 495 },
37 496 {
38 497 "cell_type": "markdown",
39 498 "metadata": {},
40 499 "source": [
41 "When trying to design an attractive widget GUI, styling becomes important.\n",
42 "Most widget views are DOM (document object model) elements that can be controlled with CSS.\n",
43 "There are two helper methods that allow the manipulation of the widget's CSS.\n",
44 "The first is the `Widget.set_css` method.\n",
45 "This method allows one or more CSS attributes to be set at once. "
500 "Most widgets have a `description` attribute, which allows a label for the widget to be defined.\n",
501 "The label of the widget has a fixed minimum width.\n",
502 "The text of the label is always right aligned and the widget is left aligned:"
46 503 ]
47 504 },
48 505 {
49 506 "cell_type": "code",
50 507 "collapsed": false,
51 508 "input": [
52 "print(widgets.DOMWidget.set_css.__doc__)"
509 "display(widgets.TextWidget(description=\"a:\"))\n",
510 "display(widgets.TextWidget(description=\"aa:\"))\n",
511 "display(widgets.TextWidget(description=\"aaa:\"))"
53 512 ],
54 513 "language": "python",
55 514 "metadata": {},
56 "outputs": [
57 {
58 "output_type": "stream",
59 "stream": "stdout",
60 "text": [
61 "Set one or more CSS properties of the widget.\n",
62 "\n",
63 " This function has two signatures:\n",
64 " - set_css(css_dict, selector='')\n",
65 " - set_css(key, value, selector='')\n",
66 "\n",
67 " Parameters\n",
68 " ----------\n",
69 " css_dict : dict\n",
70 " CSS key/value pairs to apply\n",
71 " key: unicode\n",
72 " CSS key\n",
73 " value:\n",
74 " CSS value\n",
75 " selector: unicode (optional, kwarg only)\n",
76 " JQuery selector to use to apply the CSS key/value. If no selector \n",
77 " is provided, an empty selector is used. An empty selector makes the \n",
78 " front-end try to apply the css to a default element. The default\n",
79 " element is an attribute unique to each view, which is a DOM element\n",
80 " of the view that should be styled with common CSS (see \n",
81 " `$el_to_style` in the Javascript code).\n",
82 " \n"
83 ]
84 }
85 ],
86 "prompt_number": 2
515 "outputs": [],
516 "prompt_number": 159
87 517 },
88 518 {
89 519 "cell_type": "markdown",
90 520 "metadata": {},
91 521 "source": [
92 "The second is `get_css` which allows CSS attributesto be read.\n",
93 "Note that this method will only read CSS attributes that have been set using the `set_css` method."
522 "If a label is longer than the minimum width, the widget is shifted to the right:"
94 523 ]
95 524 },
96 525 {
97 526 "cell_type": "code",
98 527 "collapsed": false,
99 528 "input": [
100 "print(widgets.DOMWidget.get_css.__doc__)"
529 "display(widgets.TextWidget(description=\"a:\"))\n",
530 "display(widgets.TextWidget(description=\"aa:\"))\n",
531 "display(widgets.TextWidget(description=\"aaa:\"))\n",
532 "display(widgets.TextWidget(description=\"aaaaaaaaaaaaaaaaaa:\"))"
101 533 ],
102 534 "language": "python",
103 535 "metadata": {},
104 "outputs": [
105 {
106 "output_type": "stream",
107 "stream": "stdout",
108 "text": [
109 "Get a CSS property of the widget.\n",
110 "\n",
111 " Note: This function does not actually request the CSS from the \n",
112 " front-end; Only properties that have been set with set_css can be read.\n",
113 "\n",
114 " Parameters\n",
115 " ----------\n",
116 " key: unicode\n",
117 " CSS key\n",
118 " selector: unicode (optional)\n",
119 " JQuery selector used when the CSS key/value was set.\n",
120 " \n"
121 ]
122 }
123 ],
124 "prompt_number": 3
536 "outputs": [],
537 "prompt_number": 160
125 538 },
126 539 {
127 540 "cell_type": "markdown",
128 541 "metadata": {},
129 542 "source": [
130 "Below is an example that applies CSS attributes to a container to emphasize text."
543 "If a `description` is not set for the widget, the label is not displayed:"
131 544 ]
132 545 },
133 546 {
134 547 "cell_type": "code",
135 548 "collapsed": false,
136 549 "input": [
137 "label = widgets.LatexWidget()\n",
138 "label.value = \"$\\\\textbf{ALERT:} Hello World!$\"\n",
139 "container = widgets.ContainerWidget(children=[label])\n",
140 "\n",
141 "# set_css used to set a single CSS attribute.\n",
142 "container.set_css('border', '3px solid black') # Border the container\n",
143 "\n",
144 "# set_css used to set multiple CSS attributes.\n",
145 "container.set_css({'padding': '6px', # Add padding to the container\n",
146 " 'background': 'yellow'}) # Fill the container yellow\n",
147 "\n",
148 "display(container)"
550 "display(widgets.TextWidget(description=\"a:\"))\n",
551 "display(widgets.TextWidget(description=\"aa:\"))\n",
552 "display(widgets.TextWidget(description=\"aaa:\"))\n",
553 "display(widgets.TextWidget())"
149 554 ],
150 555 "language": "python",
151 556 "metadata": {},
152 557 "outputs": [],
153 "prompt_number": 4
558 "prompt_number": 161
154 559 },
155 560 {
156 561 "cell_type": "heading",
157 562 "level": 1,
158 563 "metadata": {},
159 564 "source": [
160 "CSS Classes"
565 "DOM Classes"
566 ]
567 },
568 {
569 "cell_type": "markdown",
570 "metadata": {},
571 "source": [
572 "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/)."
573 ]
574 },
575 {
576 "cell_type": "heading",
577 "level": 2,
578 "metadata": {},
579 "source": [
580 "Path dependent"
161 581 ]
162 582 },
163 583 {
164 584 "cell_type": "markdown",
165 585 "metadata": {},
166 586 "source": [
167 "In some cases, it is necessary to apply CSS classes to your widgets.\n",
168 "CSS classes allow DOM elements to be indentified in Javascript and CSS.\n",
169 "The notebook defines its own set of classes to stylize its elements.\n",
170 "The `add_class` widget method allows you to add CSS classes to your widget."
587 "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."
171 588 ]
172 589 },
173 590 {
174 591 "cell_type": "code",
175 592 "collapsed": false,
176 593 "input": [
177 "print(widgets.DOMWidget.add_class.__doc__)"
594 "%%html\n",
595 "<style>\n",
596 " div.cube { display: inline; padding: 5px; }\n",
597 " div.red { background: red; }\n",
598 " div.blue { background: blue; }\n",
599 "</style>"
178 600 ],
179 601 "language": "python",
180 602 "metadata": {},
181 603 "outputs": [
182 604 {
183 "output_type": "stream",
184 "stream": "stdout",
605 "html": [
606 "<style>\n",
607 " div.cube { display: inline; padding: 5px; }\n",
608 " div.red { background: red; }\n",
609 " div.blue { background: blue; }\n",
610 "</style>"
611 ],
612 "metadata": {},
613 "output_type": "display_data",
185 614 "text": [
186 "Add class[es] to a DOM element.\n",
187 "\n",
188 " Parameters\n",
189 " ----------\n",
190 " class_names: unicode or list\n",
191 " Class name(s) to add to the DOM element(s).\n",
192 " selector: unicode (optional)\n",
193 " JQuery selector to select the DOM element(s) that the class(es) will\n",
194 " be added to.\n",
195 " \n"
615 "<IPython.core.display.HTML object>"
196 616 ]
197 617 }
198 618 ],
199 "prompt_number": 5
619 "prompt_number": 162
620 },
621 {
622 "cell_type": "code",
623 "collapsed": false,
624 "input": [
625 "from IPython.html import widgets\n",
626 "from IPython.display import display\n",
627 "html = '<br />'.join([''.join(['<div class=\"cube\">x</div>' for i in range(8)]) for j in range(8)])\n",
628 "widget = [widgets.HTMLWidget(value=html) for i in range(3)]\n",
629 "\n",
630 "display(widget[0])\n",
631 "widget[0].add_class('red', 'div.cube:nth-child(even)')\n",
632 "widget[0].remove_class('red', 'div.red:nth-child(7n+1)')\n",
633 "widget[0].add_class('blue', 'div.red:nth-child(3n+1)')"
634 ],
635 "language": "python",
636 "metadata": {},
637 "outputs": [],
638 "prompt_number": 163
639 },
640 {
641 "cell_type": "code",
642 "collapsed": false,
643 "input": [
644 "display(widget[1])\n",
645 "widget[1].remove_class('red', 'div.red:nth-child(7n+1)')\n",
646 "widget[1].add_class('blue', 'div.red:nth-child(3n+1)')\n",
647 "widget[1].add_class('red', 'div.cube:nth-child(even)')"
648 ],
649 "language": "python",
650 "metadata": {},
651 "outputs": [],
652 "prompt_number": 164
653 },
654 {
655 "cell_type": "code",
656 "collapsed": false,
657 "input": [
658 "display(widget[2])\n",
659 "widget[2].add_class('red', 'div.cube:nth-child(even)')\n",
660 "widget[2].add_class('blue', 'div.red:nth-child(3n+1)')\n",
661 "widget[2].remove_class('red', 'div.red:nth-child(7n+1)')"
662 ],
663 "language": "python",
664 "metadata": {},
665 "outputs": [],
666 "prompt_number": 165
667 },
668 {
669 "cell_type": "heading",
670 "level": 2,
671 "metadata": {},
672 "source": [
673 "Alignment classes"
674 ]
675 },
676 {
677 "cell_type": "markdown",
678 "metadata": {},
679 "source": [
680 "Widgets can be aligned using IPython specific alignment classes. These classes should work with most widgets, but were designed to be applied to `ContainerWidget`s. Examples of these classes follow:\n",
681 "\n",
682 "### Orientation classes\n",
683 "#### \"vbox\"\n",
684 "Widget containers default to this orientation.\n",
685 "<div class=\"example-container vbox\">\n",
686 "<div class=\"example-box\">A</div>\n",
687 "<div class=\"example-box med\">B</div>\n",
688 "<div class=\"example-box lrg\">C</div>\n",
689 "</div>\n",
690 "\n",
691 "#### \"hbox\"\n",
692 "<div class=\"example-container hbox\">\n",
693 "<div class=\"example-box\">A</div>\n",
694 "<div class=\"example-box med\">B</div>\n",
695 "<div class=\"example-box lrg\">C</div>\n",
696 "</div>\n",
697 "\n",
698 "### Packing classes\n",
699 "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",
700 "#### \"start\"\n",
701 "<div class=\"example-container hbox start\">\n",
702 "<div class=\"example-box\">A</div>\n",
703 "<div class=\"example-box med\">B</div>\n",
704 "<div class=\"example-box lrg\">C</div>\n",
705 "</div>\n",
706 "\n",
707 "#### \"center\"\n",
708 "<div class=\"example-container hbox center\">\n",
709 "<div class=\"example-box\">A</div>\n",
710 "<div class=\"example-box med\">B</div>\n",
711 "<div class=\"example-box lrg\">C</div>\n",
712 "</div>\n",
713 "\n",
714 "#### \"end\"\n",
715 "<div class=\"example-container hbox end\">\n",
716 "<div class=\"example-box\">A</div>\n",
717 "<div class=\"example-box med\">B</div>\n",
718 "<div class=\"example-box lrg\">C</div>\n",
719 "</div>\n",
720 "\n",
721 "### Aligning classes\n",
722 "These examples use the hbox layout to show alignment. Packing is the alignment of the widgets along the the axis perpindicular to the one that they are displayed on.\n",
723 "#### \"align-start\"\n",
724 "<div class=\"example-container hbox align-start\">\n",
725 "<div class=\"example-box\">A</div>\n",
726 "<div class=\"example-box med\">B</div>\n",
727 "<div class=\"example-box lrg\">C</div>\n",
728 "</div>\n",
729 "\n",
730 "#### \"align-center\"\n",
731 "<div class=\"example-container hbox align-center\">\n",
732 "<div class=\"example-box\">A</div>\n",
733 "<div class=\"example-box med\">B</div>\n",
734 "<div class=\"example-box lrg\">C</div>\n",
735 "</div>\n",
736 "\n",
737 "#### \"align-end\"\n",
738 "<div class=\"example-container hbox align-end\">\n",
739 "<div class=\"example-box\">A</div>\n",
740 "<div class=\"example-box med\">B</div>\n",
741 "<div class=\"example-box lrg\">C</div>\n",
742 "</div>\n",
743 "\n",
744 "### Flex classes\n",
745 "To specify how \"greedy\" a container is when filling in the remaining space of its parent, the `box-flexN` properties 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",
746 "\n",
747 "#### Example 1\n",
748 "<div class=\"example-container sm hbox center\">\n",
749 "<div class=\"example-box box-flex0\">box-flex0</div>\n",
750 "<div class=\"example-box box-flex0\">box-flex0</div>\n",
751 "<div class=\"example-box box-flex0\">box-flex0</div>\n",
752 "</div>\n",
753 "\n",
754 "#### Example 2\n",
755 "<div class=\"example-container sm hbox center\">\n",
756 "<div class=\"example-box box-flex0\">box-flex0</div>\n",
757 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
758 "<div class=\"example-box box-flex0\">box-flex0</div>\n",
759 "</div>\n",
760 "\n",
761 "#### Example 3\n",
762 "<div class=\"example-container sm hbox center\">\n",
763 "<div class=\"example-box box-flex0\">box-flex0</div>\n",
764 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
765 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
766 "</div>\n",
767 "\n",
768 "#### Example 4\n",
769 "<div class=\"example-container sm hbox center\">\n",
770 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
771 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
772 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
773 "</div>\n",
774 "\n",
775 "#### Example 5\n",
776 "<div class=\"example-container sm hbox center\">\n",
777 "<div class=\"example-box box-flex2\">box-flex2</div>\n",
778 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
779 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
780 "</div>\n",
781 "\n",
782 "#### Example 6\n",
783 "<div class=\"example-container sm hbox center\">\n",
784 "<div class=\"example-box box-flex0\">box-flex0</div>\n",
785 "<div class=\"example-box box-flex1\">box-flex1</div>\n",
786 "<div class=\"example-box box-flex2\">box-flex2</div>\n",
787 "</div>\n"
788 ]
789 },
790 {
791 "cell_type": "heading",
792 "level": 3,
793 "metadata": {},
794 "source": [
795 "Application to widgets"
796 ]
200 797 },
201 798 {
202 799 "cell_type": "markdown",
203 800 "metadata": {},
204 801 "source": [
205 "Since `add_class` is a DOM operation, **it will only affect widgets that have already been displayed**.\n",
206 "`add_class` must be called after the widget has been displayed.\n",
207 "Extending the example above, the corners of the container can be rounded by adding the `corner-all` CSS class to the container."
802 "Widget containers default as vertical boxes."
208 803 ]
209 804 },
210 805 {
211 806 "cell_type": "code",
212 807 "collapsed": false,
213 808 "input": [
214 "container = widgets.ContainerWidget()\n",
215 "container.set_css({'border': '3px solid black',\n",
216 " 'padding': '6px', \n",
217 " 'background': 'yellow'}) \n",
809 "buttons = [widgets.ButtonWidget(description=str(i)) for i in range(3)]\n",
218 810 "\n",
219 "label = widgets.LatexWidget()\n",
220 "label.value = \"$\\\\textbf{ALERT:} Hello World!$\"\n",
221 "container.children = [label]\n",
811 "container = widgets.ContainerWidget(children=buttons)\n",
812 "display(container)"
813 ],
814 "language": "python",
815 "metadata": {},
816 "outputs": [],
817 "prompt_number": 166
818 },
819 {
820 "cell_type": "markdown",
821 "metadata": {},
822 "source": [
823 "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."
824 ]
825 },
826 {
827 "cell_type": "code",
828 "collapsed": false,
829 "input": [
830 "container = widgets.ContainerWidget(children=buttons)\n",
222 831 "display(container)\n",
223 "container.add_class('corner-all') # Must be called AFTER display"
832 "container.remove_class('vbox')\n",
833 "container.add_class('hbox')"
224 834 ],
225 835 "language": "python",
226 836 "metadata": {},
227 837 "outputs": [],
228 "prompt_number": 6
838 "prompt_number": 167
229 839 },
230 840 {
231 841 "cell_type": "markdown",
232 842 "metadata": {},
233 843 "source": [
234 "The IPython notebook uses [bootstrap](http://getbootstrap.com/\u200e) for styling.\n",
235 "The example above can be simplified by using a bootstrap class:"
844 "By setting the width of the container to 100% and adding the `center` class to it, you can center the buttons."
236 845 ]
237 846 },
238 847 {
239 848 "cell_type": "code",
240 849 "collapsed": false,
241 850 "input": [
242 "label = widgets.LatexWidget(value = \"$\\\\textbf{ALERT:} Hello World!$\")\n",
243 "display(label)\n",
244 "\n",
245 "# Apply twitter bootstrap alert class to the label.\n",
246 "label.add_class(\"alert\")"
851 "container.set_css('width', '100%')\n",
852 "container.add_class('center')"
247 853 ],
248 854 "language": "python",
249 855 "metadata": {},
250 856 "outputs": [],
251 "prompt_number": 7
857 "prompt_number": 168
858 },
859 {
860 "cell_type": "heading",
861 "level": 2,
862 "metadata": {},
863 "source": [
864 "Style classes"
865 ]
252 866 },
253 867 {
254 868 "cell_type": "markdown",
255 869 "metadata": {},
256 870 "source": [
257 "The example below shows how bootstrap classes can be used to change button apearance."
871 "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/)."
872 ]
873 },
874 {
875 "cell_type": "heading",
876 "level": 3,
877 "metadata": {},
878 "source": [
879 "ButtonWidgets"
258 880 ]
259 881 },
260 882 {
@@ -262,91 +884,189 b''
262 884 "collapsed": false,
263 885 "input": [
264 886 "# List of the bootstrap button styles\n",
265 "button_classes = ['Default', 'btn-primary', 'btn-info', 'btn-success', \n",
266 " 'btn-warning', 'btn-danger', 'btn-inverse', 'btn-link']\n",
887 "classes = [\n",
888 " 'btn', \n",
889 " 'btn-primary', \n",
890 " 'btn-info', \n",
891 " 'btn-success', \n",
892 " 'btn-warning', \n",
893 " 'btn-danger', \n",
894 " 'btn-inverse', \n",
895 " 'btn-link'\n",
896 "]\n",
897 "\n",
898 "# Display the buttons in a hbox\n",
899 "container = widgets.ContainerWidget(children=[widgets.ButtonWidget(description=c) for c in classes])\n",
900 "display(container)\n",
901 "\n",
902 "# Apply classes after display\n",
903 "container.remove_class('vbox')\n",
904 "container.add_class('hbox')\n",
905 "ret = [container.children[i].add_class(c) for i, c in enumerate(classes)]"
906 ],
907 "language": "python",
908 "metadata": {},
909 "outputs": [],
910 "prompt_number": 180
911 },
912 {
913 "cell_type": "heading",
914 "level": 3,
915 "metadata": {},
916 "source": [
917 "ContainerWidgets"
918 ]
919 },
920 {
921 "cell_type": "code",
922 "collapsed": false,
923 "input": [
924 "def create_label(cls):\n",
925 " class_name = widgets.HTMLWidget(value=cls)\n",
926 " container = widgets.ContainerWidget(children=[class_name])\n",
927 " display(container)\n",
928 " container.add_class(cls)\n",
267 929 "\n",
268 "# Create each button and apply the style. Also add margin to the buttons so they space\n",
269 "# themselves nicely.\n",
270 "for i in range(8):\n",
271 " button = widgets.ButtonWidget(description=button_classes[i])\n",
272 " button.set_css(\"margin\", \"5px\")\n",
273 " display(button)\n",
274 " if i > 0: # Don't add a class the first button.\n",
275 " button.add_class(button_classes[i])\n",
276 " "
930 "ret = [create_label(c) for c in [\n",
931 " 'alert', \n",
932 " 'alert alert-error', \n",
933 " 'alert alert-success', \n",
934 " 'alert alert-info'\n",
935 "]]"
936 ],
937 "language": "python",
938 "metadata": {},
939 "outputs": [],
940 "prompt_number": 181
941 },
942 {
943 "cell_type": "heading",
944 "level": 3,
945 "metadata": {},
946 "source": [
947 "*ProgressWidgets"
948 ]
949 },
950 {
951 "cell_type": "code",
952 "collapsed": false,
953 "input": [
954 "classes = [\n",
955 " 'progress-info', \n",
956 " 'progress-success', \n",
957 " 'progress-warning', \n",
958 " 'progress-danger',\n",
959 " 'progress-striped progress-info', \n",
960 " 'progress-striped progress-success', \n",
961 " 'progress-striped progress-warning', \n",
962 " 'progress-striped progress-danger',\n",
963 " 'active progress-striped progress-info', \n",
964 " 'active progress-striped progress-success', \n",
965 " 'active progress-striped progress-warning', \n",
966 " 'active progress-striped progress-danger',\n",
967 "]\n",
968 "ws = [widgets.IntProgressWidget(value=50, description=c) for c in classes]\n",
969 "ret = [display(w) for w in ws]\n",
970 "ret = [ws[i].add_class(c) for i, c in enumerate(classes)]"
277 971 ],
278 972 "language": "python",
279 973 "metadata": {},
280 974 "outputs": [],
281 "prompt_number": 8
975 "prompt_number": 182
976 },
977 {
978 "cell_type": "heading",
979 "level": 1,
980 "metadata": {},
981 "source": [
982 "Visibility"
983 ]
282 984 },
283 985 {
284 986 "cell_type": "markdown",
285 987 "metadata": {},
286 988 "source": [
287 "It is also useful to be able to remove CSS classes from widgets.\n",
288 "The `remove_class` method allows you to remove classes from widgets that have been displayed.\n",
289 "Like `add_class`, it must be called after the widget has been displayed."
989 "Sometimes it is necessary to hide or show widgets in place, without having to redisplay the widget.\n",
990 "The `visibility` property of widgets can be used to hide or show widgets that have already been displayed (as seen below)."
290 991 ]
291 992 },
292 993 {
293 994 "cell_type": "code",
294 995 "collapsed": false,
295 996 "input": [
296 "print(widgets.DOMWidget.remove_class.__doc__)"
997 "string = widgets.LatexWidget(value=\"Hello World!\")\n",
998 "display(string) "
297 999 ],
298 1000 "language": "python",
299 1001 "metadata": {},
300 "outputs": [
301 {
302 "output_type": "stream",
303 "stream": "stdout",
304 "text": [
305 "Remove class[es] from a DOM element.\n",
306 "\n",
307 " Parameters\n",
308 " ----------\n",
309 " class_names: unicode or list\n",
310 " Class name(s) to remove from the DOM element(s).\n",
311 " selector: unicode (optional)\n",
312 " JQuery selector to select the DOM element(s) that the class(es) will\n",
313 " be removed from.\n",
314 " \n"
315 ]
316 }
1002 "outputs": [],
1003 "prompt_number": 183
1004 },
1005 {
1006 "cell_type": "code",
1007 "collapsed": false,
1008 "input": [
1009 "string.visible=False"
1010 ],
1011 "language": "python",
1012 "metadata": {},
1013 "outputs": [],
1014 "prompt_number": 184
1015 },
1016 {
1017 "cell_type": "code",
1018 "collapsed": false,
1019 "input": [
1020 "string.visible=True"
317 1021 ],
318 "prompt_number": 9
1022 "language": "python",
1023 "metadata": {},
1024 "outputs": [],
1025 "prompt_number": 185
319 1026 },
320 1027 {
321 1028 "cell_type": "markdown",
322 1029 "metadata": {},
323 1030 "source": [
324 "The example below animates an alert using different bootstrap styles."
1031 "In the example below, a form is rendered, which conditionally displays widgets depending on the state of other widgets. Try toggling the student checkbox."
325 1032 ]
326 1033 },
327 1034 {
328 1035 "cell_type": "code",
329 1036 "collapsed": false,
330 1037 "input": [
331 "import time\n",
332 "label = widgets.LatexWidget(value = \"$\\\\textbf{ALERT:} Hello World!$\")\n",
333 "display(label)\n",
1038 "form = widgets.ContainerWidget()\n",
1039 "first = widgets.TextWidget(description=\"First Name:\")\n",
1040 "last = widgets.TextWidget(description=\"Last Name:\")\n",
1041 "\n",
1042 "student = widgets.CheckboxWidget(description=\"Student:\", value=False)\n",
1043 "school_info = widgets.ContainerWidget(visible=False, children=[\n",
1044 " widgets.TextWidget(description=\"School:\"),\n",
1045 " widgets.IntTextWidget(description=\"Grade:\", min=0, max=12)\n",
1046 " ])\n",
334 1047 "\n",
335 "# Apply twitter bootstrap alert class to the label.\n",
336 "label.add_class(\"alert\")\n",
1048 "pet = widgets.TextWidget(description=\"Pet's Name:\")\n",
1049 "form.children = [first, last, student, school_info, pet]\n",
1050 "display(form)\n",
337 1051 "\n",
338 "# Animate through additional bootstrap label styles 3 times\n",
339 "additional_alert_styles = ['alert-error', 'alert-info', 'alert-success']\n",
340 "for i in range(3 * len(additional_alert_styles)):\n",
341 " label.add_class(additional_alert_styles[i % 3])\n",
342 " label.remove_class(additional_alert_styles[(i-1) % 3])\n",
343 " time.sleep(1)\n",
344 " "
1052 "def on_student_toggle(name, value):\n",
1053 " if value:\n",
1054 " school_info.visible = True\n",
1055 " else:\n",
1056 " school_info.visible = False\n",
1057 "student.on_trait_change(on_student_toggle, 'value')\n"
345 1058 ],
346 1059 "language": "python",
347 1060 "metadata": {},
348 1061 "outputs": [],
349 "prompt_number": 10
1062 "prompt_number": 186
1063 },
1064 {
1065 "cell_type": "markdown",
1066 "metadata": {},
1067 "source": [
1068 "[Next](Custom Widget - Hello World.ipynb)"
1069 ]
350 1070 }
351 1071 ],
352 1072 "metadata": {}
General Comments 0
You need to be logged in to leave comments. Login now