##// END OF EJS Templates
Merge pull request #7359 from jdfreder/tab-fix...
Min RK -
r19797:468962b1 merge
parent child Browse files
Show More
@@ -1,301 +1,325 b''
1 // Copyright (c) IPython Development Team.
1 // Copyright (c) IPython Development Team.
2 // Distributed under the terms of the Modified BSD License.
2 // Distributed under the terms of the Modified BSD License.
3
3
4 define([
4 define([
5 "widgets/js/widget",
5 "widgets/js/widget",
6 "base/js/utils",
6 "base/js/utils",
7 "jquery",
7 "jquery",
8 "bootstrap",
8 "bootstrap",
9 ], function(widget, utils, $){
9 ], function(widget, utils, $){
10
10
11 var AccordionView = widget.DOMWidgetView.extend({
11 var AccordionView = widget.DOMWidgetView.extend({
12 initialize: function(){
12 initialize: function(){
13 AccordionView.__super__.initialize.apply(this, arguments);
13 AccordionView.__super__.initialize.apply(this, arguments);
14
14
15 this.containers = [];
15 this.containers = [];
16 this.model_containers = {};
16 this.model_containers = {};
17 this.children_views = new widget.ViewList(this.add_child_view, this.remove_child_view, this);
17 this.children_views = new widget.ViewList(this.add_child_view, this.remove_child_view, this);
18 this.listenTo(this.model, 'change:children', function(model, value) {
18 this.listenTo(this.model, 'change:children', function(model, value) {
19 this.children_views.update(value);
19 this.children_views.update(value);
20 }, this);
20 }, this);
21 },
21 },
22
22
23 render: function(){
23 render: function(){
24 /**
24 /**
25 * Called when view is rendered.
25 * Called when view is rendered.
26 */
26 */
27 var guid = 'panel-group' + utils.uuid();
27 var guid = 'panel-group' + utils.uuid();
28 this.$el
28 this.$el
29 .attr('id', guid)
29 .attr('id', guid)
30 .addClass('panel-group');
30 .addClass('panel-group');
31 this.model.on('change:selected_index', function(model, value, options) {
31 this.model.on('change:selected_index', function(model, value, options) {
32 this.update_selected_index(model.previous('selected_index'), value, options);
32 this.update_selected_index(options);
33 }, this);
33 }, this);
34 this.model.on('change:_titles', function(model, value, options) {
34 this.model.on('change:_titles', function(model, value, options) {
35 this.update_titles(value);
35 this.update_titles(options);
36 }, this);
36 }, this);
37 this.on('displayed', function() {
37 this.on('displayed', function() {
38 this.update_titles();
38 this.update_titles();
39 }, this);
39 }, this);
40 this.children_views.update(this.model.get('children'));
40 this.children_views.update(this.model.get('children'));
41 },
41 },
42
42
43 update_titles: function(titles) {
43 /**
44 * Update the contents of this view
45 *
46 * Called when the model is changed. The model may have been
47 * changed by another view or by a state update from the back-end.
48 */
49 update: function(options) {
50 this.update_titles();
51 this.update_selected_index(options);
52 return TabView.__super__.update.apply(this);
53 },
54
55 update_titles: function() {
44 /**
56 /**
45 * Set tab titles
57 * Set tab titles
46 */
58 */
47 if (!titles) {
59 var titles = this.model.get('_titles');
48 titles = this.model.get('_titles');
49 }
50
51 var that = this;
60 var that = this;
52 _.each(titles, function(title, page_index) {
61 _.each(titles, function(title, page_index) {
53 var accordian = that.containers[page_index];
62 var accordian = that.containers[page_index];
54 if (accordian !== undefined) {
63 if (accordian !== undefined) {
55 accordian
64 accordian
56 .find('.panel-heading')
65 .find('.panel-heading')
57 .find('.accordion-toggle')
66 .find('.accordion-toggle')
58 .text(title);
67 .text(title);
59 }
68 }
60 });
69 });
61 },
70 },
62
71
63 update_selected_index: function(old_index, new_index, options) {
72 update_selected_index: function(options) {
64 /**
73 /**
65 * Only update the selection if the selection wasn't triggered
74 * Only update the selection if the selection wasn't triggered
66 * by the front-end. It must be triggered by the back-end.
75 * by the front-end. It must be triggered by the back-end.
67 */
76 */
68 if (options === undefined || options.updated_view != this) {
77 if (options === undefined || options.updated_view != this) {
78 var old_index = this.model.previous('selected_index');
79 var new_index = this.model.get('selected_index');
69 this.containers[old_index].find('.panel-collapse').collapse('hide');
80 this.containers[old_index].find('.panel-collapse').collapse('hide');
70 if (0 <= new_index && new_index < this.containers.length) {
81 if (0 <= new_index && new_index < this.containers.length) {
71 this.containers[new_index].find('.panel-collapse').collapse('show');
82 this.containers[new_index].find('.panel-collapse').collapse('show');
72 }
83 }
73 }
84 }
74 },
85 },
75
86
76 remove_child_view: function(view) {
87 remove_child_view: function(view) {
77 /**
88 /**
78 * Called when a child is removed from children list.
89 * Called when a child is removed from children list.
79 * TODO: does this handle two different views of the same model as children?
90 * TODO: does this handle two different views of the same model as children?
80 */
91 */
81 var model = view.model;
92 var model = view.model;
82 var accordion_group = this.model_containers[model.id];
93 var accordion_group = this.model_containers[model.id];
83 this.containers.splice(accordion_group.container_index, 1);
94 this.containers.splice(accordion_group.container_index, 1);
84 delete this.model_containers[model.id];
95 delete this.model_containers[model.id];
85 accordion_group.remove();
96 accordion_group.remove();
86 },
97 },
87
98
88 add_child_view: function(model) {
99 add_child_view: function(model) {
89 /**
100 /**
90 * Called when a child is added to children list.
101 * Called when a child is added to children list.
91 */
102 */
92 var index = this.containers.length;
103 var index = this.containers.length;
93 var uuid = utils.uuid();
104 var uuid = utils.uuid();
94 var accordion_group = $('<div />')
105 var accordion_group = $('<div />')
95 .addClass('panel panel-default')
106 .addClass('panel panel-default')
96 .appendTo(this.$el);
107 .appendTo(this.$el);
97 var accordion_heading = $('<div />')
108 var accordion_heading = $('<div />')
98 .addClass('panel-heading')
109 .addClass('panel-heading')
99 .appendTo(accordion_group);
110 .appendTo(accordion_group);
100 var that = this;
111 var that = this;
101 var accordion_toggle = $('<a />')
112 var accordion_toggle = $('<a />')
102 .addClass('accordion-toggle')
113 .addClass('accordion-toggle')
103 .attr('data-toggle', 'collapse')
114 .attr('data-toggle', 'collapse')
104 .attr('data-parent', '#' + this.$el.attr('id'))
115 .attr('data-parent', '#' + this.$el.attr('id'))
105 .attr('href', '#' + uuid)
116 .attr('href', '#' + uuid)
106 .click(function(evt){
117 .click(function(evt){
107
118
108 // Calling model.set will trigger all of the other views of the
119 // Calling model.set will trigger all of the other views of the
109 // model to update.
120 // model to update.
110 that.model.set("selected_index", index, {updated_view: that});
121 that.model.set("selected_index", index, {updated_view: that});
111 that.touch();
122 that.touch();
112 })
123 })
113 .text('Page ' + index)
124 .text('Page ' + index)
114 .appendTo(accordion_heading);
125 .appendTo(accordion_heading);
115 var accordion_body = $('<div />', {id: uuid})
126 var accordion_body = $('<div />', {id: uuid})
116 .addClass('panel-collapse collapse')
127 .addClass('panel-collapse collapse')
117 .appendTo(accordion_group);
128 .appendTo(accordion_group);
118 var accordion_inner = $('<div />')
129 var accordion_inner = $('<div />')
119 .addClass('panel-body')
130 .addClass('panel-body')
120 .appendTo(accordion_body);
131 .appendTo(accordion_body);
121 var container_index = this.containers.push(accordion_group) - 1;
132 var container_index = this.containers.push(accordion_group) - 1;
122 accordion_group.container_index = container_index;
133 accordion_group.container_index = container_index;
123 this.model_containers[model.id] = accordion_group;
134 this.model_containers[model.id] = accordion_group;
124
135
125 var dummy = $('<div/>');
136 var dummy = $('<div/>');
126 accordion_inner.append(dummy);
137 accordion_inner.append(dummy);
127 return this.create_child_view(model).then(function(view) {
138 return this.create_child_view(model).then(function(view) {
128 dummy.replaceWith(view.$el);
139 dummy.replaceWith(view.$el);
129 that.update();
140 that.update();
130 that.update_titles();
141 that.update_titles();
131
142
132 // Trigger the displayed event of the child view.
143 // Trigger the displayed event of the child view.
133 that.after_displayed(function() {
144 that.after_displayed(function() {
134 view.trigger('displayed');
145 view.trigger('displayed');
135 });
146 });
136 return view;
147 return view;
137 }).catch(utils.reject("Couldn't add child view to box", true));
148 }).catch(utils.reject("Couldn't add child view to box", true));
138 },
149 },
139
150
140 remove: function() {
151 remove: function() {
141 /**
152 /**
142 * We remove this widget before removing the children as an optimization
153 * We remove this widget before removing the children as an optimization
143 * we want to remove the entire container from the DOM first before
154 * we want to remove the entire container from the DOM first before
144 * removing each individual child separately.
155 * removing each individual child separately.
145 */
156 */
146 AccordionView.__super__.remove.apply(this, arguments);
157 AccordionView.__super__.remove.apply(this, arguments);
147 this.children_views.remove();
158 this.children_views.remove();
148 },
159 },
149 });
160 });
150
161
151
162
152 var TabView = widget.DOMWidgetView.extend({
163 var TabView = widget.DOMWidgetView.extend({
153 initialize: function() {
164 initialize: function() {
154 /**
165 /**
155 * Public constructor.
166 * Public constructor.
156 */
167 */
157 TabView.__super__.initialize.apply(this, arguments);
168 TabView.__super__.initialize.apply(this, arguments);
158
169
159 this.containers = [];
170 this.containers = [];
160 this.children_views = new widget.ViewList(this.add_child_view, this.remove_child_view, this);
171 this.children_views = new widget.ViewList(this.add_child_view, this.remove_child_view, this);
161 this.listenTo(this.model, 'change:children', function(model, value) {
172 this.listenTo(this.model, 'change:children', function(model, value) {
162 this.children_views.update(value);
173 this.children_views.update(value);
163 }, this);
174 }, this);
164 },
175 },
165
176
166 render: function(){
177 render: function(){
167 /**
178 /**
168 * Called when view is rendered.
179 * Called when view is rendered.
169 */
180 */
170 var uuid = 'tabs'+utils.uuid();
181 var uuid = 'tabs'+utils.uuid();
171 var that = this;
182 var that = this;
172 this.$tabs = $('<div />', {id: uuid})
183 this.$tabs = $('<div />', {id: uuid})
173 .addClass('nav')
184 .addClass('nav')
174 .addClass('nav-tabs')
185 .addClass('nav-tabs')
175 .appendTo(this.$el);
186 .appendTo(this.$el);
176 this.$tab_contents = $('<div />', {id: uuid + 'Content'})
187 this.$tab_contents = $('<div />', {id: uuid + 'Content'})
177 .addClass('tab-content')
188 .addClass('tab-content')
178 .appendTo(this.$el);
189 .appendTo(this.$el);
179 this.children_views.update(this.model.get('children'));
190 this.children_views.update(this.model.get('children'));
180 },
191 },
181
192
182 update_attr: function(name, value) {
193 update_attr: function(name, value) {
183 /**
194 /**
184 * Set a css attr of the widget view.
195 * Set a css attr of the widget view.
185 */
196 */
186 if (name == 'padding' || name == 'margin') {
197 if (name == 'padding' || name == 'margin') {
187 this.$el.css(name, value);
198 this.$el.css(name, value);
188 } else {
199 } else {
189 this.$tabs.css(name, value);
200 this.$tabs.css(name, value);
190 }
201 }
191 },
202 },
192
203
193 remove_child_view: function(view) {
204 remove_child_view: function(view) {
194 /**
205 /**
195 * Called when a child is removed from children list.
206 * Called when a child is removed from children list.
196 */
207 */
197 this.containers.splice(view.parent_tab.tab_text_index, 1);
208 this.containers.splice(view.parent_tab.tab_text_index, 1);
198 view.parent_tab.remove();
209 view.parent_tab.remove();
199 view.parent_container.remove();
210 view.parent_container.remove();
200 view.remove();
211 view.remove();
201 },
212 },
202
213
203 add_child_view: function(model) {
214 add_child_view: function(model) {
204 /**
215 /**
205 * Called when a child is added to children list.
216 * Called when a child is added to children list.
206 */
217 */
207 var index = this.containers.length;
218 var index = this.containers.length;
208 var uuid = utils.uuid();
219 var uuid = utils.uuid();
209
220
210 var that = this;
221 var that = this;
211 var tab = $('<li />')
222 var tab = $('<li />')
212 .css('list-style-type', 'none')
223 .css('list-style-type', 'none')
213 .appendTo(this.$tabs);
224 .appendTo(this.$tabs);
214
215
225
216 var tab_text = $('<a />')
226 var tab_text = $('<a />')
217 .attr('href', '#' + uuid)
227 .attr('href', '#' + uuid)
218 .attr('data-toggle', 'tab')
228 .attr('data-toggle', 'tab')
219 .text('Page ' + index)
229 .text('Page ' + index)
220 .appendTo(tab)
230 .appendTo(tab)
221 .click(function (e) {
231 .click(function (e) {
222
232
223 // Calling model.set will trigger all of the other views of the
233 // Calling model.set will trigger all of the other views of the
224 // model to update.
234 // model to update.
225 that.model.set("selected_index", index, {updated_view: that});
235 that.model.set("selected_index", index, {updated_view: that});
226 that.touch();
236 that.touch();
227 that.select_page(index);
237 that.select_page(index);
228 });
238 });
229 tab.tab_text_index = that.containers.push(tab_text) - 1;
239 tab.tab_text_index = that.containers.push(tab_text) - 1;
230
240
231 var dummy = $('<div />');
241 var dummy = $('<div />');
232 var contents_div = $('<div />', {id: uuid})
242 var contents_div = $('<div />', {id: uuid})
233 .addClass('tab-pane')
243 .addClass('tab-pane')
234 .addClass('fade')
244 .addClass('fade')
235 .append(dummy)
245 .append(dummy)
236 .appendTo(that.$tab_contents);
246 .appendTo(that.$tab_contents);
237
247
248 this.update();
238 return this.create_child_view(model).then(function(view) {
249 return this.create_child_view(model).then(function(view) {
239 dummy.replaceWith(view.$el);
250 dummy.replaceWith(view.$el);
240 view.parent_tab = tab;
251 view.parent_tab = tab;
241 view.parent_container = contents_div;
252 view.parent_container = contents_div;
242
253
243 // Trigger the displayed event of the child view.
254 // Trigger the displayed event of the child view.
244 that.after_displayed(function() {
255 that.after_displayed(function() {
245 view.trigger('displayed');
256 view.trigger('displayed');
257 that.update();
246 });
258 });
247 return view;
259 return view;
248 }).catch(utils.reject("Couldn't add child view to box", true));
260 }).catch(utils.reject("Couldn't add child view to box", true));
249 },
261 },
250
262
251 update: function(options) {
263 update: function(options) {
252 /**
264 /**
253 * Update the contents of this view
265 * Update the contents of this view
254 *
266 *
255 * Called when the model is changed. The model may have been
267 * Called when the model is changed. The model may have been
256 * changed by another view or by a state update from the back-end.
268 * changed by another view or by a state update from the back-end.
257 */
269 */
258 if (options === undefined || options.updated_view != this) {
270 this.update_titles();
259 // Set tab titles
271 this.update_selected_index(options);
260 var titles = this.model.get('_titles');
272 return TabView.__super__.update.apply(this);
261 var that = this;
273 },
262 _.each(titles, function(title, page_index) {
263 var tab_text = that.containers[page_index];
264 if (tab_text !== undefined) {
265 tab_text.text(title);
266 }
267 });
268
274
275 /**
276 * Updates the tab page titles.
277 */
278 update_titles: function() {
279 var titles = this.model.get('_titles');
280 var that = this;
281 _.each(titles, function(title, page_index) {
282 var tab_text = that.containers[page_index];
283 if (tab_text !== undefined) {
284 tab_text.text(title);
285 }
286 });
287 },
288
289 /**
290 * Updates the tab page titles.
291 */
292 update_selected_index: function(options) {
293 if (options === undefined || options.updated_view != this) {
269 var selected_index = this.model.get('selected_index');
294 var selected_index = this.model.get('selected_index');
270 if (0 <= selected_index && selected_index < this.containers.length) {
295 if (0 <= selected_index && selected_index < this.containers.length) {
271 this.select_page(selected_index);
296 this.select_page(selected_index);
272 }
297 }
273 }
298 }
274 return TabView.__super__.update.apply(this);
275 },
299 },
276
300
277 select_page: function(index) {
301 select_page: function(index) {
278 /**
302 /**
279 * Select a page.
303 * Select a page.
280 */
304 */
281 this.$tabs.find('li')
305 this.$tabs.find('li')
282 .removeClass('active');
306 .removeClass('active');
283 this.containers[index].tab('show');
307 this.containers[index].tab('show');
284 },
308 },
285
309
286 remove: function() {
310 remove: function() {
287 /**
311 /**
288 * We remove this widget before removing the children as an optimization
312 * We remove this widget before removing the children as an optimization
289 * we want to remove the entire container from the DOM first before
313 * we want to remove the entire container from the DOM first before
290 * removing each individual child separately.
314 * removing each individual child separately.
291 */
315 */
292 TabView.__super__.remove.apply(this, arguments);
316 TabView.__super__.remove.apply(this, arguments);
293 this.children_views.remove();
317 this.children_views.remove();
294 },
318 },
295 });
319 });
296
320
297 return {
321 return {
298 'AccordionView': AccordionView,
322 'AccordionView': AccordionView,
299 'TabView': TabView,
323 'TabView': TabView,
300 };
324 };
301 });
325 });
@@ -1,584 +1,584 b''
1 {
1 {
2 "cells": [
2 "cells": [
3 {
3 {
4 "cell_type": "markdown",
4 "cell_type": "markdown",
5 "metadata": {},
5 "metadata": {},
6 "source": [
6 "source": [
7 "[Index](Index.ipynb) - [Back](Widget Events.ipynb) - [Next](Custom Widget - Hello World.ipynb)"
7 "[Index](Index.ipynb) - [Back](Widget Events.ipynb) - [Next](Custom Widget - Hello World.ipynb)"
8 ]
8 ]
9 },
9 },
10 {
10 {
11 "cell_type": "code",
11 "cell_type": "code",
12 "execution_count": null,
12 "execution_count": null,
13 "metadata": {
13 "metadata": {
14 "collapsed": false
14 "collapsed": false
15 },
15 },
16 "outputs": [],
16 "outputs": [],
17 "source": [
17 "source": [
18 "%%html\n",
18 "%%html\n",
19 "<style>\n",
19 "<style>\n",
20 ".example-container { background: #999999; padding: 2px; min-height: 100px; }\n",
20 ".example-container { background: #999999; padding: 2px; min-height: 100px; }\n",
21 ".example-container.sm { min-height: 50px; }\n",
21 ".example-container.sm { min-height: 50px; }\n",
22 ".example-box { background: #9999FF; width: 50px; height: 50px; text-align: center; vertical-align: middle; color: white; font-weight: bold; margin: 2px;}\n",
22 ".example-box { background: #9999FF; width: 50px; height: 50px; text-align: center; vertical-align: middle; color: white; font-weight: bold; margin: 2px;}\n",
23 ".example-box.med { width: 65px; height: 65px; } \n",
23 ".example-box.med { width: 65px; height: 65px; } \n",
24 ".example-box.lrg { width: 80px; height: 80px; } \n",
24 ".example-box.lrg { width: 80px; height: 80px; } \n",
25 "</style>"
25 "</style>"
26 ]
26 ]
27 },
27 },
28 {
28 {
29 "cell_type": "code",
29 "cell_type": "code",
30 "execution_count": null,
30 "execution_count": null,
31 "metadata": {
31 "metadata": {
32 "collapsed": false
32 "collapsed": false
33 },
33 },
34 "outputs": [],
34 "outputs": [],
35 "source": [
35 "source": [
36 "from IPython.html import widgets\n",
36 "from IPython.html import widgets\n",
37 "from IPython.display import display"
37 "from IPython.display import display"
38 ]
38 ]
39 },
39 },
40 {
40 {
41 "cell_type": "markdown",
41 "cell_type": "markdown",
42 "metadata": {
42 "metadata": {
43 "slideshow": {
43 "slideshow": {
44 "slide_type": "slide"
44 "slide_type": "slide"
45 }
45 }
46 },
46 },
47 "source": [
47 "source": [
48 "# Widget Styling"
48 "# Widget Styling"
49 ]
49 ]
50 },
50 },
51 {
51 {
52 "cell_type": "markdown",
52 "cell_type": "markdown",
53 "metadata": {},
53 "metadata": {},
54 "source": [
54 "source": [
55 "## Basic styling"
55 "## Basic styling"
56 ]
56 ]
57 },
57 },
58 {
58 {
59 "cell_type": "markdown",
59 "cell_type": "markdown",
60 "metadata": {},
60 "metadata": {},
61 "source": [
61 "source": [
62 "The widgets distributed with IPython can be styled by setting the following traits:\n",
62 "The widgets distributed with IPython can be styled by setting the following traits:\n",
63 "\n",
63 "\n",
64 "- width \n",
64 "- width \n",
65 "- height \n",
65 "- height \n",
66 "- fore_color \n",
66 "- fore_color \n",
67 "- back_color \n",
67 "- back_color \n",
68 "- border_color \n",
68 "- border_color \n",
69 "- border_width \n",
69 "- border_width \n",
70 "- border_style \n",
70 "- border_style \n",
71 "- font_style \n",
71 "- font_style \n",
72 "- font_weight \n",
72 "- font_weight \n",
73 "- font_size \n",
73 "- font_size \n",
74 "- font_family \n",
74 "- font_family \n",
75 "\n",
75 "\n",
76 "The example below shows how a `Button` widget can be styled:"
76 "The example below shows how a `Button` widget can be styled:"
77 ]
77 ]
78 },
78 },
79 {
79 {
80 "cell_type": "code",
80 "cell_type": "code",
81 "execution_count": null,
81 "execution_count": null,
82 "metadata": {
82 "metadata": {
83 "collapsed": false
83 "collapsed": false
84 },
84 },
85 "outputs": [],
85 "outputs": [],
86 "source": [
86 "source": [
87 "button = widgets.Button(\n",
87 "button = widgets.Button(\n",
88 " description='Hello World!',\n",
88 " description='Hello World!',\n",
89 " width=100, # Integers are interpreted as pixel measurements.\n",
89 " width=100, # Integers are interpreted as pixel measurements.\n",
90 " height='2em', # em is valid HTML unit of measurement.\n",
90 " height='2em', # em is valid HTML unit of measurement.\n",
91 " color='lime', # Colors can be set by name,\n",
91 " color='lime', # Colors can be set by name,\n",
92 " background_color='#0022FF', # and also by color code.\n",
92 " background_color='#0022FF', # and also by color code.\n",
93 " border_color='red')\n",
93 " border_color='red')\n",
94 "display(button)"
94 "display(button)"
95 ]
95 ]
96 },
96 },
97 {
97 {
98 "cell_type": "markdown",
98 "cell_type": "markdown",
99 "metadata": {
99 "metadata": {
100 "slideshow": {
100 "slideshow": {
101 "slide_type": "slide"
101 "slide_type": "slide"
102 }
102 }
103 },
103 },
104 "source": [
104 "source": [
105 "## Parent/child relationships"
105 "## Parent/child relationships"
106 ]
106 ]
107 },
107 },
108 {
108 {
109 "cell_type": "markdown",
109 "cell_type": "markdown",
110 "metadata": {},
110 "metadata": {},
111 "source": [
111 "source": [
112 "To display widget A inside widget B, widget A must be a child of widget B. 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."
112 "To display widget A inside widget B, widget A must be a child of widget B. 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."
113 ]
113 ]
114 },
114 },
115 {
115 {
116 "cell_type": "code",
116 "cell_type": "code",
117 "execution_count": null,
117 "execution_count": null,
118 "metadata": {
118 "metadata": {
119 "collapsed": false
119 "collapsed": false
120 },
120 },
121 "outputs": [],
121 "outputs": [],
122 "source": [
122 "source": [
123 "from IPython.display import display\n",
123 "from IPython.display import display\n",
124 "\n",
124 "\n",
125 "float_range = widgets.FloatSlider()\n",
125 "float_range = widgets.FloatSlider()\n",
126 "string = widgets.Text(value='hi')\n",
126 "string = widgets.Text(value='hi')\n",
127 "container = widgets.Box(children=[float_range, string])\n",
127 "container = widgets.Box(children=[float_range, string])\n",
128 "\n",
128 "\n",
129 "container.border_color = 'red'\n",
129 "container.border_color = 'red'\n",
130 "container.border_style = 'dotted'\n",
130 "container.border_style = 'dotted'\n",
131 "container.border_width = 3\n",
131 "container.border_width = 3\n",
132 "display(container) # Displays the `container` and all of it's children."
132 "display(container) # Displays the `container` and all of it's children."
133 ]
133 ]
134 },
134 },
135 {
135 {
136 "cell_type": "markdown",
136 "cell_type": "markdown",
137 "metadata": {},
137 "metadata": {},
138 "source": [
138 "source": [
139 "### After the parent is displayed"
139 "### After the parent is displayed"
140 ]
140 ]
141 },
141 },
142 {
142 {
143 "cell_type": "markdown",
143 "cell_type": "markdown",
144 "metadata": {
144 "metadata": {
145 "slideshow": {
145 "slideshow": {
146 "slide_type": "slide"
146 "slide_type": "slide"
147 }
147 }
148 },
148 },
149 "source": [
149 "source": [
150 "Children **can be added to parents** after the parent has been displayed. The **parent is responsible for rendering its children**."
150 "Children **can be added to parents** after the parent has been displayed. The **parent is responsible for rendering its children**."
151 ]
151 ]
152 },
152 },
153 {
153 {
154 "cell_type": "code",
154 "cell_type": "code",
155 "execution_count": null,
155 "execution_count": null,
156 "metadata": {
156 "metadata": {
157 "collapsed": false
157 "collapsed": false
158 },
158 },
159 "outputs": [],
159 "outputs": [],
160 "source": [
160 "source": [
161 "container = widgets.Box()\n",
161 "container = widgets.Box()\n",
162 "container.border_color = 'red'\n",
162 "container.border_color = 'red'\n",
163 "container.border_style = 'dotted'\n",
163 "container.border_style = 'dotted'\n",
164 "container.border_width = 3\n",
164 "container.border_width = 3\n",
165 "display(container)\n",
165 "display(container)\n",
166 "\n",
166 "\n",
167 "int_range = widgets.IntSlider()\n",
167 "int_range = widgets.IntSlider()\n",
168 "container.children=[int_range]"
168 "container.children=[int_range]"
169 ]
169 ]
170 },
170 },
171 {
171 {
172 "cell_type": "markdown",
172 "cell_type": "markdown",
173 "metadata": {
173 "metadata": {
174 "slideshow": {
174 "slideshow": {
175 "slide_type": "slide"
175 "slide_type": "slide"
176 }
176 }
177 },
177 },
178 "source": [
178 "source": [
179 "## Fancy boxes"
179 "## Fancy boxes"
180 ]
180 ]
181 },
181 },
182 {
182 {
183 "cell_type": "markdown",
183 "cell_type": "markdown",
184 "metadata": {},
184 "metadata": {},
185 "source": [
185 "source": [
186 "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 **`Accordion` or a `Tab` in combination with one `Box` 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**."
186 "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 **`Accordion` or a `Tab` in combination with one `Box` per set of widgets** (as seen below). The \"pages\" of these widgets are their children. To set the titles of the pages, one can **call `set_title`**."
187 ]
187 ]
188 },
188 },
189 {
189 {
190 "cell_type": "markdown",
190 "cell_type": "markdown",
191 "metadata": {},
191 "metadata": {},
192 "source": [
192 "source": [
193 "### Accordion"
193 "### Accordion"
194 ]
194 ]
195 },
195 },
196 {
196 {
197 "cell_type": "code",
197 "cell_type": "code",
198 "execution_count": null,
198 "execution_count": null,
199 "metadata": {
199 "metadata": {
200 "collapsed": false
200 "collapsed": false
201 },
201 },
202 "outputs": [],
202 "outputs": [],
203 "source": [
203 "source": [
204 "name1 = widgets.Text(description='Location:')\n",
204 "name1 = widgets.Text(description='Location:')\n",
205 "zip1 = widgets.BoundedIntText(description='Zip:', min=0, max=99999)\n",
205 "zip1 = widgets.BoundedIntText(description='Zip:', min=0, max=99999)\n",
206 "page1 = widgets.Box(children=[name1, zip1])\n",
206 "page1 = widgets.Box(children=[name1, zip1])\n",
207 "\n",
207 "\n",
208 "name2 = widgets.Text(description='Location:')\n",
208 "name2 = widgets.Text(description='Location:')\n",
209 "zip2 = widgets.BoundedIntText(description='Zip:', min=0, max=99999)\n",
209 "zip2 = widgets.BoundedIntText(description='Zip:', min=0, max=99999)\n",
210 "page2 = widgets.Box(children=[name2, zip2])\n",
210 "page2 = widgets.Box(children=[name2, zip2])\n",
211 "\n",
211 "\n",
212 "accord = widgets.Accordion(children=[page1, page2])\n",
212 "accord = widgets.Accordion(children=[page1, page2])\n",
213 "display(accord)\n",
213 "display(accord)\n",
214 "\n",
214 "\n",
215 "accord.set_title(0, 'From')\n",
215 "accord.set_title(0, 'From')\n",
216 "accord.set_title(1, 'To')"
216 "accord.set_title(1, 'To')"
217 ]
217 ]
218 },
218 },
219 {
219 {
220 "cell_type": "markdown",
220 "cell_type": "markdown",
221 "metadata": {
221 "metadata": {
222 "slideshow": {
222 "slideshow": {
223 "slide_type": "slide"
223 "slide_type": "slide"
224 }
224 }
225 },
225 },
226 "source": [
226 "source": [
227 "### TabWidget"
227 "### TabWidget"
228 ]
228 ]
229 },
229 },
230 {
230 {
231 "cell_type": "code",
231 "cell_type": "code",
232 "execution_count": null,
232 "execution_count": null,
233 "metadata": {
233 "metadata": {
234 "collapsed": false
234 "collapsed": false
235 },
235 },
236 "outputs": [],
236 "outputs": [],
237 "source": [
237 "source": [
238 "name = widgets.Text(description='Name:')\n",
238 "name = widgets.Text(description='Name:')\n",
239 "color = widgets.Dropdown(description='Color:', values=['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'])\n",
239 "color = widgets.Dropdown(description='Color:', values=['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'])\n",
240 "page1 = widgets.Box(children=[name, color])\n",
240 "page1 = widgets.Box(children=[name, color])\n",
241 "\n",
241 "\n",
242 "age = widgets.IntSlider(description='Age:', min=0, max=120, value=50)\n",
242 "age = widgets.IntSlider(description='Age:', min=0, max=120, value=50)\n",
243 "gender = widgets.RadioButtons(description='Gender:', values=['male', 'female'])\n",
243 "gender = widgets.RadioButtons(description='Gender:', values=['male', 'female'])\n",
244 "page2 = widgets.Box(children=[age, gender])\n",
244 "page2 = widgets.Box(children=[age, gender])\n",
245 "\n",
245 "\n",
246 "tabs = widgets.Tab(children=[page1, page2])\n",
246 "tabs = widgets.Tab(children=[page1, page2])\n",
247 "display(tabs)\n",
247 "display(tabs)\n",
248 "\n",
248 "\n",
249 "tabs.set_title(0, 'Name')\n",
249 "tabs.set_title(0, 'Name')\n",
250 "tabs.set_title(1, 'Details')"
250 "tabs.set_title(1, 'Details')"
251 ]
251 ]
252 },
252 },
253 {
253 {
254 "cell_type": "markdown",
254 "cell_type": "markdown",
255 "metadata": {
255 "metadata": {
256 "slideshow": {
256 "slideshow": {
257 "slide_type": "slide"
257 "slide_type": "slide"
258 }
258 }
259 },
259 },
260 "source": [
260 "source": [
261 "# Alignment"
261 "# Alignment"
262 ]
262 ]
263 },
263 },
264 {
264 {
265 "cell_type": "markdown",
265 "cell_type": "markdown",
266 "metadata": {},
266 "metadata": {},
267 "source": [
267 "source": [
268 "Most widgets have a **`description` attribute**, which allows a label for the widget to be defined.\n",
268 "Most widgets have a **`description` attribute**, which allows a label for the widget to be defined.\n",
269 "The label of the widget **has a fixed minimum width**.\n",
269 "The label of the widget **has a fixed minimum width**.\n",
270 "The text of the label is **always right aligned and the widget is left aligned**:"
270 "The text of the label is **always right aligned and the widget is left aligned**:"
271 ]
271 ]
272 },
272 },
273 {
273 {
274 "cell_type": "code",
274 "cell_type": "code",
275 "execution_count": null,
275 "execution_count": null,
276 "metadata": {
276 "metadata": {
277 "collapsed": false
277 "collapsed": false
278 },
278 },
279 "outputs": [],
279 "outputs": [],
280 "source": [
280 "source": [
281 "display(widgets.Text(description=\"a:\"))\n",
281 "display(widgets.Text(description=\"a:\"))\n",
282 "display(widgets.Text(description=\"aa:\"))\n",
282 "display(widgets.Text(description=\"aa:\"))\n",
283 "display(widgets.Text(description=\"aaa:\"))"
283 "display(widgets.Text(description=\"aaa:\"))"
284 ]
284 ]
285 },
285 },
286 {
286 {
287 "cell_type": "markdown",
287 "cell_type": "markdown",
288 "metadata": {
288 "metadata": {
289 "slideshow": {
289 "slideshow": {
290 "slide_type": "slide"
290 "slide_type": "slide"
291 }
291 }
292 },
292 },
293 "source": [
293 "source": [
294 "If a **label is longer** than the minimum width, the **widget is shifted to the right**:"
294 "If a **label is longer** than the minimum width, the **widget is shifted to the right**:"
295 ]
295 ]
296 },
296 },
297 {
297 {
298 "cell_type": "code",
298 "cell_type": "code",
299 "execution_count": null,
299 "execution_count": null,
300 "metadata": {
300 "metadata": {
301 "collapsed": false
301 "collapsed": false
302 },
302 },
303 "outputs": [],
303 "outputs": [],
304 "source": [
304 "source": [
305 "display(widgets.Text(description=\"a:\"))\n",
305 "display(widgets.Text(description=\"a:\"))\n",
306 "display(widgets.Text(description=\"aa:\"))\n",
306 "display(widgets.Text(description=\"aa:\"))\n",
307 "display(widgets.Text(description=\"aaa:\"))\n",
307 "display(widgets.Text(description=\"aaa:\"))\n",
308 "display(widgets.Text(description=\"aaaaaaaaaaaaaaaaaa:\"))"
308 "display(widgets.Text(description=\"aaaaaaaaaaaaaaaaaa:\"))"
309 ]
309 ]
310 },
310 },
311 {
311 {
312 "cell_type": "markdown",
312 "cell_type": "markdown",
313 "metadata": {
313 "metadata": {
314 "slideshow": {
314 "slideshow": {
315 "slide_type": "slide"
315 "slide_type": "slide"
316 }
316 }
317 },
317 },
318 "source": [
318 "source": [
319 "If a `description` is **not set** for the widget, the **label is not displayed**:"
319 "If a `description` is **not set** for the widget, the **label is not displayed**:"
320 ]
320 ]
321 },
321 },
322 {
322 {
323 "cell_type": "code",
323 "cell_type": "code",
324 "execution_count": null,
324 "execution_count": null,
325 "metadata": {
325 "metadata": {
326 "collapsed": false
326 "collapsed": false
327 },
327 },
328 "outputs": [],
328 "outputs": [],
329 "source": [
329 "source": [
330 "display(widgets.Text(description=\"a:\"))\n",
330 "display(widgets.Text(description=\"a:\"))\n",
331 "display(widgets.Text(description=\"aa:\"))\n",
331 "display(widgets.Text(description=\"aa:\"))\n",
332 "display(widgets.Text(description=\"aaa:\"))\n",
332 "display(widgets.Text(description=\"aaa:\"))\n",
333 "display(widgets.Text())"
333 "display(widgets.Text())"
334 ]
334 ]
335 },
335 },
336 {
336 {
337 "cell_type": "markdown",
337 "cell_type": "markdown",
338 "metadata": {
338 "metadata": {
339 "slideshow": {
339 "slideshow": {
340 "slide_type": "slide"
340 "slide_type": "slide"
341 }
341 }
342 },
342 },
343 "source": [
343 "source": [
344 "## Flex boxes"
344 "## Flex boxes"
345 ]
345 ]
346 },
346 },
347 {
347 {
348 "cell_type": "markdown",
348 "cell_type": "markdown",
349 "metadata": {},
349 "metadata": {},
350 "source": [
350 "source": [
351 "Widgets can be aligned using the `FlexBox`, `HBox`, and `VBox` widgets."
351 "Widgets can be aligned using the `FlexBox`, `HBox`, and `VBox` widgets."
352 ]
352 ]
353 },
353 },
354 {
354 {
355 "cell_type": "markdown",
355 "cell_type": "markdown",
356 "metadata": {
356 "metadata": {
357 "slideshow": {
357 "slideshow": {
358 "slide_type": "slide"
358 "slide_type": "slide"
359 }
359 }
360 },
360 },
361 "source": [
361 "source": [
362 "### Application to widgets"
362 "### Application to widgets"
363 ]
363 ]
364 },
364 },
365 {
365 {
366 "cell_type": "markdown",
366 "cell_type": "markdown",
367 "metadata": {},
367 "metadata": {},
368 "source": [
368 "source": [
369 "Widgets display vertically by default:"
369 "Widgets display vertically by default:"
370 ]
370 ]
371 },
371 },
372 {
372 {
373 "cell_type": "code",
373 "cell_type": "code",
374 "execution_count": null,
374 "execution_count": null,
375 "metadata": {
375 "metadata": {
376 "collapsed": false
376 "collapsed": false
377 },
377 },
378 "outputs": [],
378 "outputs": [],
379 "source": [
379 "source": [
380 "buttons = [widgets.Button(description=str(i)) for i in range(3)]\n",
380 "buttons = [widgets.Button(description=str(i)) for i in range(3)]\n",
381 "display(*buttons)"
381 "display(*buttons)"
382 ]
382 ]
383 },
383 },
384 {
384 {
385 "cell_type": "markdown",
385 "cell_type": "markdown",
386 "metadata": {
386 "metadata": {
387 "slideshow": {
387 "slideshow": {
388 "slide_type": "slide"
388 "slide_type": "slide"
389 }
389 }
390 },
390 },
391 "source": [
391 "source": [
392 "### Using hbox"
392 "### Using hbox"
393 ]
393 ]
394 },
394 },
395 {
395 {
396 "cell_type": "markdown",
396 "cell_type": "markdown",
397 "metadata": {},
397 "metadata": {},
398 "source": [
398 "source": [
399 "To make widgets display horizontally, you need to **child them to a `HBox` widget**."
399 "To make widgets display horizontally, you need to **child them to a `HBox` widget**."
400 ]
400 ]
401 },
401 },
402 {
402 {
403 "cell_type": "code",
403 "cell_type": "code",
404 "execution_count": null,
404 "execution_count": null,
405 "metadata": {
405 "metadata": {
406 "collapsed": false
406 "collapsed": false
407 },
407 },
408 "outputs": [],
408 "outputs": [],
409 "source": [
409 "source": [
410 "container = widgets.HBox(children=buttons)\n",
410 "container = widgets.HBox(children=buttons)\n",
411 "display(container)"
411 "display(container)"
412 ]
412 ]
413 },
413 },
414 {
414 {
415 "cell_type": "markdown",
415 "cell_type": "markdown",
416 "metadata": {},
416 "metadata": {},
417 "source": [
417 "source": [
418 "By setting the width of the container to 100% and its `pack` to `center`, you can center the buttons."
418 "By setting the width of the container to 100% and its `pack` to `center`, you can center the buttons."
419 ]
419 ]
420 },
420 },
421 {
421 {
422 "cell_type": "code",
422 "cell_type": "code",
423 "execution_count": null,
423 "execution_count": null,
424 "metadata": {
424 "metadata": {
425 "collapsed": false
425 "collapsed": false
426 },
426 },
427 "outputs": [],
427 "outputs": [],
428 "source": [
428 "source": [
429 "container.width = '100%'\n",
429 "container.width = '100%'\n",
430 "container.pack = 'center'"
430 "container.pack = 'center'"
431 ]
431 ]
432 },
432 },
433 {
433 {
434 "cell_type": "markdown",
434 "cell_type": "markdown",
435 "metadata": {
435 "metadata": {
436 "slideshow": {
436 "slideshow": {
437 "slide_type": "slide"
437 "slide_type": "slide"
438 }
438 }
439 },
439 },
440 "source": [
440 "source": [
441 "## Visibility"
441 "## Visibility"
442 ]
442 ]
443 },
443 },
444 {
444 {
445 "cell_type": "markdown",
445 "cell_type": "markdown",
446 "metadata": {},
446 "metadata": {},
447 "source": [
447 "source": [
448 "Sometimes it is necessary to **hide or show widgets** in place, **without having to re-display** the widget.\n",
448 "Sometimes it is necessary to **hide or show widgets** in place, **without having to re-display** the widget.\n",
449 "The `visible` property of widgets can be used to hide or show **widgets that have already been displayed** (as seen below). The `visible` property can be:\n",
449 "The `visible` property of widgets can be used to hide or show **widgets that have already been displayed** (as seen below). The `visible` property can be:\n",
450 "* `True` - the widget is displayed\n",
450 "* `True` - the widget is displayed\n",
451 "* `False` - the widget is hidden, and the empty space where the widget would be is collapsed\n",
451 "* `False` - the widget is hidden, and the empty space where the widget would be is collapsed\n",
452 "* `None` - the widget is hidden, and the empty space where the widget would be is shown"
452 "* `None` - the widget is hidden, and the empty space where the widget would be is shown"
453 ]
453 ]
454 },
454 },
455 {
455 {
456 "cell_type": "code",
456 "cell_type": "code",
457 "execution_count": null,
457 "execution_count": null,
458 "metadata": {
458 "metadata": {
459 "collapsed": false
459 "collapsed": false
460 },
460 },
461 "outputs": [],
461 "outputs": [],
462 "source": [
462 "source": [
463 "w1 = widgets.Latex(value=\"First line\")\n",
463 "w1 = widgets.Latex(value=\"First line\")\n",
464 "w2 = widgets.Latex(value=\"Second line\")\n",
464 "w2 = widgets.Latex(value=\"Second line\")\n",
465 "w3 = widgets.Latex(value=\"Third line\")\n",
465 "w3 = widgets.Latex(value=\"Third line\")\n",
466 "display(w1, w2, w3)"
466 "display(w1, w2, w3)"
467 ]
467 ]
468 },
468 },
469 {
469 {
470 "cell_type": "code",
470 "cell_type": "code",
471 "execution_count": null,
471 "execution_count": null,
472 "metadata": {
472 "metadata": {
473 "collapsed": true
473 "collapsed": true
474 },
474 },
475 "outputs": [],
475 "outputs": [],
476 "source": [
476 "source": [
477 "w2.visible=None"
477 "w2.visible=None"
478 ]
478 ]
479 },
479 },
480 {
480 {
481 "cell_type": "code",
481 "cell_type": "code",
482 "execution_count": null,
482 "execution_count": null,
483 "metadata": {
483 "metadata": {
484 "collapsed": false
484 "collapsed": false
485 },
485 },
486 "outputs": [],
486 "outputs": [],
487 "source": [
487 "source": [
488 "w2.visible=False"
488 "w2.visible=False"
489 ]
489 ]
490 },
490 },
491 {
491 {
492 "cell_type": "code",
492 "cell_type": "code",
493 "execution_count": null,
493 "execution_count": null,
494 "metadata": {
494 "metadata": {
495 "collapsed": false
495 "collapsed": false
496 },
496 },
497 "outputs": [],
497 "outputs": [],
498 "source": [
498 "source": [
499 "w2.visible=True"
499 "w2.visible=True"
500 ]
500 ]
501 },
501 },
502 {
502 {
503 "cell_type": "markdown",
503 "cell_type": "markdown",
504 "metadata": {
504 "metadata": {
505 "slideshow": {
505 "slideshow": {
506 "slide_type": "slide"
506 "slide_type": "slide"
507 }
507 }
508 },
508 },
509 "source": [
509 "source": [
510 "### Another example"
510 "### Another example"
511 ]
511 ]
512 },
512 },
513 {
513 {
514 "cell_type": "markdown",
514 "cell_type": "markdown",
515 "metadata": {},
515 "metadata": {},
516 "source": [
516 "source": [
517 "In the example below, a form is rendered, which conditionally displays widgets depending on the state of other widgets. Try toggling the student checkbox."
517 "In the example below, a form is rendered, which conditionally displays widgets depending on the state of other widgets. Try toggling the student checkbox."
518 ]
518 ]
519 },
519 },
520 {
520 {
521 "cell_type": "code",
521 "cell_type": "code",
522 "execution_count": null,
522 "execution_count": null,
523 "metadata": {
523 "metadata": {
524 "collapsed": false
524 "collapsed": false
525 },
525 },
526 "outputs": [],
526 "outputs": [],
527 "source": [
527 "source": [
528 "form = widgets.VBox()\n",
528 "form = widgets.VBox()\n",
529 "first = widgets.Text(description=\"First Name:\")\n",
529 "first = widgets.Text(description=\"First Name:\")\n",
530 "last = widgets.Text(description=\"Last Name:\")\n",
530 "last = widgets.Text(description=\"Last Name:\")\n",
531 "\n",
531 "\n",
532 "student = widgets.Checkbox(description=\"Student:\", value=False)\n",
532 "student = widgets.Checkbox(description=\"Student:\", value=False)\n",
533 "school_info = widgets.VBox(visible=False, children=[\n",
533 "school_info = widgets.VBox(visible=False, children=[\n",
534 " widgets.Text(description=\"School:\"),\n",
534 " widgets.Text(description=\"School:\"),\n",
535 " widgets.IntText(description=\"Grade:\", min=0, max=12)\n",
535 " widgets.IntText(description=\"Grade:\", min=0, max=12)\n",
536 " ])\n",
536 " ])\n",
537 "\n",
537 "\n",
538 "pet = widgets.Text(description=\"Pet's Name:\")\n",
538 "pet = widgets.Text(description=\"Pet's Name:\")\n",
539 "form.children = [first, last, student, school_info, pet]\n",
539 "form.children = [first, last, student, school_info, pet]\n",
540 "display(form)\n",
540 "display(form)\n",
541 "\n",
541 "\n",
542 "def on_student_toggle(name, value):\n",
542 "def on_student_toggle(name, value):\n",
543 " if value:\n",
543 " if value:\n",
544 " school_info.visible = True\n",
544 " school_info.visible = True\n",
545 " else:\n",
545 " else:\n",
546 " school_info.visible = False\n",
546 " school_info.visible = False\n",
547 "student.on_trait_change(on_student_toggle, 'value')\n"
547 "student.on_trait_change(on_student_toggle, 'value')\n"
548 ]
548 ]
549 },
549 },
550 {
550 {
551 "cell_type": "markdown",
551 "cell_type": "markdown",
552 "metadata": {},
552 "metadata": {},
553 "source": [
553 "source": [
554 "[Index](Index.ipynb) - [Back](Widget Events.ipynb) - [Next](Custom Widget - Hello World.ipynb)"
554 "[Index](Index.ipynb) - [Back](Widget Events.ipynb) - [Next](Custom Widget - Hello World.ipynb)"
555 ]
555 ]
556 }
556 }
557 ],
557 ],
558 "metadata": {
558 "metadata": {
559 "cell_tags": [
559 "cell_tags": [
560 [
560 [
561 "<None>",
561 "<None>",
562 null
562 null
563 ]
563 ]
564 ],
564 ],
565 "kernelspec": {
565 "kernelspec": {
566 "display_name": "IPython (Python 2)",
566 "display_name": "IPython (Python 2)",
567 "name": "python2"
567 "name": "python2"
568 },
568 },
569 "language_info": {
569 "language_info": {
570 "codemirror_mode": {
570 "codemirror_mode": {
571 "name": "ipython",
571 "name": "ipython",
572 "version": 2
572 "version": 2
573 },
573 },
574 "file_extension": ".py",
574 "file_extension": ".py",
575 "mimetype": "text/x-python",
575 "mimetype": "text/x-python",
576 "name": "python",
576 "name": "python",
577 "nbconvert_exporter": "python",
577 "nbconvert_exporter": "python",
578 "pygments_lexer": "ipython2",
578 "pygments_lexer": "ipython2",
579 "version": "2.7.6"
579 "version": "2.7.6"
580 }
580 }
581 },
581 },
582 "nbformat": 4,
582 "nbformat": 4,
583 "nbformat_minor": 0
583 "nbformat_minor": 0
584 } No newline at end of file
584 }
General Comments 0
You need to be logged in to leave comments. Login now