##// END OF EJS Templates
remove more hard coded layout
Matthias BUSSONNIER -
Show More
@@ -1,393 +1,393 b''
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2012 The IPython Development Team
2 // Copyright (C) 2012 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // CellToolbar
9 // CellToolbar
10 //============================================================================
10 //============================================================================
11
11
12
12
13 /**
13 /**
14 * A Module to control the per-cell toolbar.
14 * A Module to control the per-cell toolbar.
15 * @module IPython
15 * @module IPython
16 * @namespace IPython
16 * @namespace IPython
17 * @submodule CellToolbar
17 * @submodule CellToolbar
18 */
18 */
19 var IPython = (function (IPython) {
19 var IPython = (function (IPython) {
20 "use strict";
20 "use strict";
21
21
22 /**
22 /**
23 * @constructor
23 * @constructor
24 * @class CellToolbar
24 * @class CellToolbar
25 * @param {The cell to attach the metadata UI to} cell
25 * @param {The cell to attach the metadata UI to} cell
26 */
26 */
27 var CellToolbar = function (cell) {
27 var CellToolbar = function (cell) {
28 CellToolbar._instances.push(this);
28 CellToolbar._instances.push(this);
29 this.cell = cell;
29 this.cell = cell;
30 this.create_element();
30 this.create_element();
31 this.rebuild();
31 this.rebuild();
32 return this;
32 return this;
33 };
33 };
34
34
35
35
36 CellToolbar.prototype.create_element = function () {
36 CellToolbar.prototype.create_element = function () {
37 this.inner_element = $('<div/>').addClass('celltoolbar hbox reverse')
37 this.inner_element = $('<div/>').addClass('celltoolbar')
38 this.element = $('<div/>').addClass('ctb_hideshow')
38 this.element = $('<div/>').addClass('ctb_hideshow')
39 .append(this.inner_element);
39 .append(this.inner_element);
40 };
40 };
41
41
42
42
43 // The default css style for the outer celltoolbar div
43 // The default css style for the outer celltoolbar div
44 // (ctb_hideshow) is display: none. We add the ctb_show
44 // (ctb_hideshow) is display: none. We add the ctb_show
45 // class to either 1) the body to show all cell's toolbars
45 // class to either 1) the body to show all cell's toolbars
46 // or 2) to the individual celltoolbar divs to show just one
46 // or 2) to the individual celltoolbar divs to show just one
47 // cell's toolbar.
47 // cell's toolbar.
48
48
49 CellToolbar.global_hide = function () {
49 CellToolbar.global_hide = function () {
50 $('body').removeClass('ctb_show');
50 $('body').removeClass('ctb_show');
51 }
51 }
52
52
53
53
54 CellToolbar.global_show = function () {
54 CellToolbar.global_show = function () {
55 $('body').addClass('ctb_show');
55 $('body').addClass('ctb_show');
56 }
56 }
57
57
58
58
59 CellToolbar.prototype.hide = function () {
59 CellToolbar.prototype.hide = function () {
60 this.element.removeClass('ctb_show');
60 this.element.removeClass('ctb_show');
61 }
61 }
62
62
63
63
64 CellToolbar.prototype.show = function () {
64 CellToolbar.prototype.show = function () {
65 this.element.addClass('ctb_show');
65 this.element.addClass('ctb_show');
66 }
66 }
67
67
68
68
69 /**
69 /**
70 * Class variable that should contain a dict of all availlable callback
70 * Class variable that should contain a dict of all availlable callback
71 * we need to think of wether or not we allow nested namespace
71 * we need to think of wether or not we allow nested namespace
72 * @property _callback_dict
72 * @property _callback_dict
73 * @private
73 * @private
74 * @static
74 * @static
75 * @type Dict
75 * @type Dict
76 */
76 */
77 CellToolbar._callback_dict = {};
77 CellToolbar._callback_dict = {};
78
78
79
79
80 /**
80 /**
81 * Class variable that should contain the reverse order list of the button
81 * Class variable that should contain the reverse order list of the button
82 * to add to the toolbar of each cell
82 * to add to the toolbar of each cell
83 * @property _ui_controls_list
83 * @property _ui_controls_list
84 * @private
84 * @private
85 * @static
85 * @static
86 * @type List
86 * @type List
87 */
87 */
88 CellToolbar._ui_controls_list = [];
88 CellToolbar._ui_controls_list = [];
89
89
90
90
91 /**
91 /**
92 * Class variable that should contains the CellToolbar instances for each
92 * Class variable that should contains the CellToolbar instances for each
93 * cell of the notebook
93 * cell of the notebook
94 *
94 *
95 * @private
95 * @private
96 * @property _instances
96 * @property _instances
97 * @static
97 * @static
98 * @type List
98 * @type List
99 */
99 */
100 CellToolbar._instances =[]
100 CellToolbar._instances =[]
101
101
102
102
103 /**
103 /**
104 * keep a list of all the availlabel presets for the toolbar
104 * keep a list of all the availlabel presets for the toolbar
105 * @private
105 * @private
106 * @property _presets
106 * @property _presets
107 * @static
107 * @static
108 * @type Dict
108 * @type Dict
109 */
109 */
110 CellToolbar._presets ={}
110 CellToolbar._presets ={}
111
111
112
112
113 // this is by design not a prototype.
113 // this is by design not a prototype.
114 /**
114 /**
115 * Register a callback to create an UI element in a cell toolbar.
115 * Register a callback to create an UI element in a cell toolbar.
116 * @method register_callback
116 * @method register_callback
117 * @param name {String} name to use to refer to the callback. It is advised to use a prefix with the name
117 * @param name {String} name to use to refer to the callback. It is advised to use a prefix with the name
118 * for easier sorting and avoid collision
118 * for easier sorting and avoid collision
119 * @param callback {function(div, cell)} callback that will be called to generate the ui element
119 * @param callback {function(div, cell)} callback that will be called to generate the ui element
120 *
120 *
121 *
121 *
122 * The callback will receive the following element :
122 * The callback will receive the following element :
123 *
123 *
124 * * a div in which to add element.
124 * * a div in which to add element.
125 * * the cell it is responsible from
125 * * the cell it is responsible from
126 *
126 *
127 * @example
127 * @example
128 *
128 *
129 * Example that create callback for a button that toggle between `true` and `false` label,
129 * Example that create callback for a button that toggle between `true` and `false` label,
130 * with the metadata under the key 'foo' to reflect the status of the button.
130 * with the metadata under the key 'foo' to reflect the status of the button.
131 *
131 *
132 * // first param reference to a DOM div
132 * // first param reference to a DOM div
133 * // second param reference to the cell.
133 * // second param reference to the cell.
134 * var toggle = function(div, cell) {
134 * var toggle = function(div, cell) {
135 * var button_container = $(div)
135 * var button_container = $(div)
136 *
136 *
137 * // let's create a button that show the current value of the metadata
137 * // let's create a button that show the current value of the metadata
138 * var button = $('<div/>').button({label:String(cell.metadata.foo)});
138 * var button = $('<div/>').button({label:String(cell.metadata.foo)});
139 *
139 *
140 * // On click, change the metadata value and update the button label
140 * // On click, change the metadata value and update the button label
141 * button.click(function(){
141 * button.click(function(){
142 * var v = cell.metadata.foo;
142 * var v = cell.metadata.foo;
143 * cell.metadata.foo = !v;
143 * cell.metadata.foo = !v;
144 * button.button("option", "label", String(!v));
144 * button.button("option", "label", String(!v));
145 * })
145 * })
146 *
146 *
147 * // add the button to the DOM div.
147 * // add the button to the DOM div.
148 * button_container.append(button);
148 * button_container.append(button);
149 * }
149 * }
150 *
150 *
151 * // now we register the callback under the name `foo` to give the
151 * // now we register the callback under the name `foo` to give the
152 * // user the ability to use it later
152 * // user the ability to use it later
153 * CellToolbar.register_callback('foo', toggle);
153 * CellToolbar.register_callback('foo', toggle);
154 */
154 */
155 CellToolbar.register_callback = function(name, callback){
155 CellToolbar.register_callback = function(name, callback){
156 // Overwrite if it already exists.
156 // Overwrite if it already exists.
157 CellToolbar._callback_dict[name] = callback;
157 CellToolbar._callback_dict[name] = callback;
158 };
158 };
159
159
160
160
161 /**
161 /**
162 * Register a preset of UI element in a cell toolbar.
162 * Register a preset of UI element in a cell toolbar.
163 * Not supported Yet.
163 * Not supported Yet.
164 * @method register_preset
164 * @method register_preset
165 * @param name {String} name to use to refer to the preset. It is advised to use a prefix with the name
165 * @param name {String} name to use to refer to the preset. It is advised to use a prefix with the name
166 * for easier sorting and avoid collision
166 * for easier sorting and avoid collision
167 * @param preset_list {List of String} reverse order of the button in the toolbar. Each String of the list
167 * @param preset_list {List of String} reverse order of the button in the toolbar. Each String of the list
168 * should correspond to a name of a registerd callback.
168 * should correspond to a name of a registerd callback.
169 *
169 *
170 * @private
170 * @private
171 * @example
171 * @example
172 *
172 *
173 * CellToolbar.register_callback('foo.c1', function(div, cell){...});
173 * CellToolbar.register_callback('foo.c1', function(div, cell){...});
174 * CellToolbar.register_callback('foo.c2', function(div, cell){...});
174 * CellToolbar.register_callback('foo.c2', function(div, cell){...});
175 * CellToolbar.register_callback('foo.c3', function(div, cell){...});
175 * CellToolbar.register_callback('foo.c3', function(div, cell){...});
176 * CellToolbar.register_callback('foo.c4', function(div, cell){...});
176 * CellToolbar.register_callback('foo.c4', function(div, cell){...});
177 * CellToolbar.register_callback('foo.c5', function(div, cell){...});
177 * CellToolbar.register_callback('foo.c5', function(div, cell){...});
178 *
178 *
179 * CellToolbar.register_preset('foo.foo_preset1', ['foo.c1', 'foo.c2', 'foo.c5'])
179 * CellToolbar.register_preset('foo.foo_preset1', ['foo.c1', 'foo.c2', 'foo.c5'])
180 * CellToolbar.register_preset('foo.foo_preset2', ['foo.c4', 'foo.c5'])
180 * CellToolbar.register_preset('foo.foo_preset2', ['foo.c4', 'foo.c5'])
181 */
181 */
182 CellToolbar.register_preset = function(name, preset_list) {
182 CellToolbar.register_preset = function(name, preset_list) {
183 CellToolbar._presets[name] = preset_list
183 CellToolbar._presets[name] = preset_list
184 $([IPython.events]).trigger('preset_added.CellToolbar', {name: name});
184 $([IPython.events]).trigger('preset_added.CellToolbar', {name: name});
185 };
185 };
186
186
187
187
188 /**
188 /**
189 * List the names of the presets that are currently registered.
189 * List the names of the presets that are currently registered.
190 *
190 *
191 * @method list_presets
191 * @method list_presets
192 * @static
192 * @static
193 */
193 */
194 CellToolbar.list_presets = function() {
194 CellToolbar.list_presets = function() {
195 var keys = [];
195 var keys = [];
196 for (var k in CellToolbar._presets) {
196 for (var k in CellToolbar._presets) {
197 keys.push(k);
197 keys.push(k);
198 }
198 }
199 return keys;
199 return keys;
200 };
200 };
201
201
202
202
203 /**
203 /**
204 * Activate an UI preset from `register_preset`
204 * Activate an UI preset from `register_preset`
205 *
205 *
206 * This does not update the selection UI.
206 * This does not update the selection UI.
207 *
207 *
208 * @method activate_preset
208 * @method activate_preset
209 * @param preset_name {String} string corresponding to the preset name
209 * @param preset_name {String} string corresponding to the preset name
210 *
210 *
211 * @static
211 * @static
212 * @private
212 * @private
213 * @example
213 * @example
214 *
214 *
215 * CellToolbar.activate_preset('foo.foo_preset1');
215 * CellToolbar.activate_preset('foo.foo_preset1');
216 */
216 */
217 CellToolbar.activate_preset= function(preset_name){
217 CellToolbar.activate_preset= function(preset_name){
218 var preset = CellToolbar._presets[preset_name];
218 var preset = CellToolbar._presets[preset_name];
219
219
220 if(preset != undefined){
220 if(preset != undefined){
221 CellToolbar._ui_controls_list = preset;
221 CellToolbar._ui_controls_list = preset;
222 CellToolbar.rebuild_all();
222 CellToolbar.rebuild_all();
223 }
223 }
224 }
224 }
225
225
226
226
227 /**
227 /**
228 * This should be called on the class and not on a instance as it will trigger
228 * This should be called on the class and not on a instance as it will trigger
229 * rebuild of all the instances.
229 * rebuild of all the instances.
230 * @method rebuild_all
230 * @method rebuild_all
231 * @static
231 * @static
232 *
232 *
233 */
233 */
234 CellToolbar.rebuild_all = function(){
234 CellToolbar.rebuild_all = function(){
235 for(var i in CellToolbar._instances){
235 for(var i in CellToolbar._instances){
236 CellToolbar._instances[i].rebuild();
236 CellToolbar._instances[i].rebuild();
237 }
237 }
238 }
238 }
239
239
240 /**
240 /**
241 * Rebuild all the button on the toolbar to update it's state.
241 * Rebuild all the button on the toolbar to update it's state.
242 * @method rebuild
242 * @method rebuild
243 */
243 */
244 CellToolbar.prototype.rebuild = function(){
244 CellToolbar.prototype.rebuild = function(){
245 // strip evrything from the div
245 // strip evrything from the div
246 // which is probabli metainner.
246 // which is probabli metainner.
247 // or this.element.
247 // or this.element.
248 this.inner_element.empty();
248 this.inner_element.empty();
249
249
250 var cdict = CellToolbar._callback_dict;
250 var cdict = CellToolbar._callback_dict;
251 var preset = CellToolbar._ui_controls_list;
251 var preset = CellToolbar._ui_controls_list;
252 // Yes we iterate on the class varaible, not the instance one.
252 // Yes we iterate on the class varaible, not the instance one.
253 for ( var index in CellToolbar._ui_controls_list){
253 for ( var index in CellToolbar._ui_controls_list){
254 var local_div = $('<div/>').addClass('button_container');
254 var local_div = $('<div/>').addClass('button_container');
255 // Note,
255 // Note,
256 // do this the other way, wrap in try/catch and don't append if any errors.
256 // do this the other way, wrap in try/catch and don't append if any errors.
257 this.inner_element.append(local_div)
257 this.inner_element.append(local_div)
258 cdict[preset[index]](local_div, this.cell)
258 cdict[preset[index]](local_div, this.cell)
259 }
259 }
260 }
260 }
261
261
262
262
263 /**
263 /**
264 */
264 */
265 CellToolbar.utils = {};
265 CellToolbar.utils = {};
266
266
267
267
268 /**
268 /**
269 * A utility function to generate bindings between a checkbox and cell/metadata
269 * A utility function to generate bindings between a checkbox and cell/metadata
270 * @method utils.checkbox_ui_generator
270 * @method utils.checkbox_ui_generator
271 * @static
271 * @static
272 *
272 *
273 * @param name {string} Label in front of the checkbox
273 * @param name {string} Label in front of the checkbox
274 * @param setter {function( cell, newValue )}
274 * @param setter {function( cell, newValue )}
275 * A setter method to set the newValue
275 * A setter method to set the newValue
276 * @param getter {function( cell )}
276 * @param getter {function( cell )}
277 * A getter methods which return the current value.
277 * A getter methods which return the current value.
278 *
278 *
279 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
279 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
280 *
280 *
281 * @example
281 * @example
282 *
282 *
283 * An exmple that bind the subkey `slideshow.isSectionStart` to a checkbox with a `New Slide` label
283 * An exmple that bind the subkey `slideshow.isSectionStart` to a checkbox with a `New Slide` label
284 *
284 *
285 * var newSlide = CellToolbar.utils.checkbox_ui_generator('New Slide',
285 * var newSlide = CellToolbar.utils.checkbox_ui_generator('New Slide',
286 * // setter
286 * // setter
287 * function(cell, value){
287 * function(cell, value){
288 * // we check that the slideshow namespace exist and create it if needed
288 * // we check that the slideshow namespace exist and create it if needed
289 * if (cell.metadata.slideshow == undefined){cell.metadata.slideshow = {}}
289 * if (cell.metadata.slideshow == undefined){cell.metadata.slideshow = {}}
290 * // set the value
290 * // set the value
291 * cell.metadata.slideshow.isSectionStart = value
291 * cell.metadata.slideshow.isSectionStart = value
292 * },
292 * },
293 * //geter
293 * //geter
294 * function(cell){ var ns = cell.metadata.slideshow;
294 * function(cell){ var ns = cell.metadata.slideshow;
295 * // if the slideshow namespace does not exist return `undefined`
295 * // if the slideshow namespace does not exist return `undefined`
296 * // (will be interpreted as `false` by checkbox) otherwise
296 * // (will be interpreted as `false` by checkbox) otherwise
297 * // return the value
297 * // return the value
298 * return (ns == undefined)? undefined: ns.isSectionStart
298 * return (ns == undefined)? undefined: ns.isSectionStart
299 * }
299 * }
300 * );
300 * );
301 *
301 *
302 * CellToolbar.register_callback('newSlide', newSlide);
302 * CellToolbar.register_callback('newSlide', newSlide);
303 *
303 *
304 */
304 */
305 CellToolbar.utils.checkbox_ui_generator = function(name, setter, getter){
305 CellToolbar.utils.checkbox_ui_generator = function(name, setter, getter){
306 return function(div, cell) {
306 return function(div, cell) {
307 var button_container = $(div)
307 var button_container = $(div)
308
308
309 var chkb = $('<input/>').attr('type', 'checkbox');
309 var chkb = $('<input/>').attr('type', 'checkbox');
310 var lbl = $('<label/>').append($('<span/>').text(name));
310 var lbl = $('<label/>').append($('<span/>').text(name));
311 lbl.append(chkb);
311 lbl.append(chkb);
312 chkb.attr("checked", getter(cell));
312 chkb.attr("checked", getter(cell));
313
313
314 chkb.click(function(){
314 chkb.click(function(){
315 var v = getter(cell);
315 var v = getter(cell);
316 setter(cell, !v);
316 setter(cell, !v);
317 chkb.attr("checked", !v);
317 chkb.attr("checked", !v);
318 })
318 })
319 button_container.append($('<div/>').append(lbl));
319 button_container.append($('<div/>').append(lbl));
320
320
321 }
321 }
322 }
322 }
323
323
324
324
325 /**
325 /**
326 * A utility function to generate bindings between a dropdown list cell
326 * A utility function to generate bindings between a dropdown list cell
327 * @method utils.select_ui_generator
327 * @method utils.select_ui_generator
328 * @static
328 * @static
329 *
329 *
330 * @param list_list {list of sublist} List of sublist of metadata value and name in the dropdown list.
330 * @param list_list {list of sublist} List of sublist of metadata value and name in the dropdown list.
331 * subslit shoud contain 2 element each, first a string that woul be displayed in the dropdown list,
331 * subslit shoud contain 2 element each, first a string that woul be displayed in the dropdown list,
332 * and second the corresponding value to be passed to setter/return by getter. the corresponding value
332 * and second the corresponding value to be passed to setter/return by getter. the corresponding value
333 * should not be "undefined" or behavior can be unexpected.
333 * should not be "undefined" or behavior can be unexpected.
334 * @param setter {function( cell, newValue )}
334 * @param setter {function( cell, newValue )}
335 * A setter method to set the newValue
335 * A setter method to set the newValue
336 * @param getter {function( cell )}
336 * @param getter {function( cell )}
337 * A getter methods which return the current value of the metadata.
337 * A getter methods which return the current value of the metadata.
338 * @param [label=""] {String} optionnal label for the dropdown menu
338 * @param [label=""] {String} optionnal label for the dropdown menu
339 *
339 *
340 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
340 * @return callback {function( div, cell )} Callback to be passed to `register_callback`
341 *
341 *
342 * @example
342 * @example
343 *
343 *
344 * var select_type = CellToolbar.utils.select_ui_generator([
344 * var select_type = CellToolbar.utils.select_ui_generator([
345 * ["<None>" , "None" ],
345 * ["<None>" , "None" ],
346 * ["Header Slide" , "header_slide" ],
346 * ["Header Slide" , "header_slide" ],
347 * ["Slide" , "slide" ],
347 * ["Slide" , "slide" ],
348 * ["Fragment" , "fragment" ],
348 * ["Fragment" , "fragment" ],
349 * ["Skip" , "skip" ],
349 * ["Skip" , "skip" ],
350 * ],
350 * ],
351 * // setter
351 * // setter
352 * function(cell, value){
352 * function(cell, value){
353 * // we check that the slideshow namespace exist and create it if needed
353 * // we check that the slideshow namespace exist and create it if needed
354 * if (cell.metadata.slideshow == undefined){cell.metadata.slideshow = {}}
354 * if (cell.metadata.slideshow == undefined){cell.metadata.slideshow = {}}
355 * // set the value
355 * // set the value
356 * cell.metadata.slideshow.slide_type = value
356 * cell.metadata.slideshow.slide_type = value
357 * },
357 * },
358 * //geter
358 * //geter
359 * function(cell){ var ns = cell.metadata.slideshow;
359 * function(cell){ var ns = cell.metadata.slideshow;
360 * // if the slideshow namespace does not exist return `undefined`
360 * // if the slideshow namespace does not exist return `undefined`
361 * // (will be interpreted as `false` by checkbox) otherwise
361 * // (will be interpreted as `false` by checkbox) otherwise
362 * // return the value
362 * // return the value
363 * return (ns == undefined)? undefined: ns.slide_type
363 * return (ns == undefined)? undefined: ns.slide_type
364 * }
364 * }
365 * CellToolbar.register_callback('slideshow.select', select_type);
365 * CellToolbar.register_callback('slideshow.select', select_type);
366 *
366 *
367 */
367 */
368 CellToolbar.utils.select_ui_generator = function(list_list, setter, getter, label){
368 CellToolbar.utils.select_ui_generator = function(list_list, setter, getter, label){
369 label= label? label: "";
369 label= label? label: "";
370 return function(div, cell) {
370 return function(div, cell) {
371 var button_container = $(div)
371 var button_container = $(div)
372 var lbl = $("<label/>").append($('<span/>').text(label));
372 var lbl = $("<label/>").append($('<span/>').text(label));
373 var select = $('<select/>').addClass('ui-widget ui-widget-content');
373 var select = $('<select/>').addClass('ui-widget ui-widget-content');
374 for(var itemn in list_list){
374 for(var itemn in list_list){
375 var opt = $('<option/>');
375 var opt = $('<option/>');
376 opt.attr('value', list_list[itemn][1])
376 opt.attr('value', list_list[itemn][1])
377 opt.text(list_list[itemn][0])
377 opt.text(list_list[itemn][0])
378 select.append(opt);
378 select.append(opt);
379 }
379 }
380 select.val(getter(cell));
380 select.val(getter(cell));
381 select.change(function(){
381 select.change(function(){
382 setter(cell, select.val());
382 setter(cell, select.val());
383 });
383 });
384 button_container.append($('<div/>').append(lbl).append(select));
384 button_container.append($('<div/>').append(lbl).append(select));
385
385
386 }
386 }
387 };
387 };
388
388
389
389
390 IPython.CellToolbar = CellToolbar;
390 IPython.CellToolbar = CellToolbar;
391
391
392 return IPython;
392 return IPython;
393 }(IPython));
393 }(IPython));
@@ -1,681 +1,681 b''
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008 The IPython Development Team
2 // Copyright (C) 2008 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // OutputArea
9 // OutputArea
10 //============================================================================
10 //============================================================================
11
11
12 /**
12 /**
13 * @module IPython
13 * @module IPython
14 * @namespace IPython
14 * @namespace IPython
15 * @submodule OutputArea
15 * @submodule OutputArea
16 */
16 */
17 var IPython = (function (IPython) {
17 var IPython = (function (IPython) {
18 "use strict";
18 "use strict";
19
19
20 var utils = IPython.utils;
20 var utils = IPython.utils;
21
21
22 /**
22 /**
23 * @class OutputArea
23 * @class OutputArea
24 *
24 *
25 * @constructor
25 * @constructor
26 */
26 */
27
27
28 var OutputArea = function (selector, prompt_area) {
28 var OutputArea = function (selector, prompt_area) {
29 this.selector = selector;
29 this.selector = selector;
30 this.wrapper = $(selector);
30 this.wrapper = $(selector);
31 this.outputs = [];
31 this.outputs = [];
32 this.collapsed = false;
32 this.collapsed = false;
33 this.scrolled = false;
33 this.scrolled = false;
34 this.clear_queued = null;
34 this.clear_queued = null;
35 if (prompt_area === undefined) {
35 if (prompt_area === undefined) {
36 this.prompt_area = true;
36 this.prompt_area = true;
37 } else {
37 } else {
38 this.prompt_area = prompt_area;
38 this.prompt_area = prompt_area;
39 }
39 }
40 this.create_elements();
40 this.create_elements();
41 this.style();
41 this.style();
42 this.bind_events();
42 this.bind_events();
43 };
43 };
44
44
45 OutputArea.prototype.create_elements = function () {
45 OutputArea.prototype.create_elements = function () {
46 this.element = $("<div/>");
46 this.element = $("<div/>");
47 this.collapse_button = $("<div/>");
47 this.collapse_button = $("<div/>");
48 this.prompt_overlay = $("<div/>");
48 this.prompt_overlay = $("<div/>");
49 this.wrapper.append(this.prompt_overlay);
49 this.wrapper.append(this.prompt_overlay);
50 this.wrapper.append(this.element);
50 this.wrapper.append(this.element);
51 this.wrapper.append(this.collapse_button);
51 this.wrapper.append(this.collapse_button);
52 };
52 };
53
53
54
54
55 OutputArea.prototype.style = function () {
55 OutputArea.prototype.style = function () {
56 this.collapse_button.hide();
56 this.collapse_button.hide();
57 this.prompt_overlay.hide();
57 this.prompt_overlay.hide();
58
58
59 this.wrapper.addClass('output_wrapper');
59 this.wrapper.addClass('output_wrapper');
60 this.element.addClass('output vbox');
60 this.element.addClass('output');
61
61
62 this.collapse_button.addClass("btn output_collapsed");
62 this.collapse_button.addClass("btn output_collapsed");
63 this.collapse_button.attr('title', 'click to expand output');
63 this.collapse_button.attr('title', 'click to expand output');
64 this.collapse_button.html('. . .');
64 this.collapse_button.html('. . .');
65
65
66 this.prompt_overlay.addClass('out_prompt_overlay prompt');
66 this.prompt_overlay.addClass('out_prompt_overlay prompt');
67 this.prompt_overlay.attr('title', 'click to expand output; double click to hide output');
67 this.prompt_overlay.attr('title', 'click to expand output; double click to hide output');
68
68
69 this.collapse();
69 this.collapse();
70 };
70 };
71
71
72 /**
72 /**
73 * Should the OutputArea scroll?
73 * Should the OutputArea scroll?
74 * Returns whether the height (in lines) exceeds a threshold.
74 * Returns whether the height (in lines) exceeds a threshold.
75 *
75 *
76 * @private
76 * @private
77 * @method _should_scroll
77 * @method _should_scroll
78 * @param [lines=100]{Integer}
78 * @param [lines=100]{Integer}
79 * @return {Bool}
79 * @return {Bool}
80 *
80 *
81 */
81 */
82 OutputArea.prototype._should_scroll = function (lines) {
82 OutputArea.prototype._should_scroll = function (lines) {
83 if (lines <=0 ){ return }
83 if (lines <=0 ){ return }
84 if (!lines) {
84 if (!lines) {
85 lines = 100;
85 lines = 100;
86 }
86 }
87 // line-height from http://stackoverflow.com/questions/1185151
87 // line-height from http://stackoverflow.com/questions/1185151
88 var fontSize = this.element.css('font-size');
88 var fontSize = this.element.css('font-size');
89 var lineHeight = Math.floor(parseInt(fontSize.replace('px','')) * 1.5);
89 var lineHeight = Math.floor(parseInt(fontSize.replace('px','')) * 1.5);
90
90
91 return (this.element.height() > lines * lineHeight);
91 return (this.element.height() > lines * lineHeight);
92 };
92 };
93
93
94
94
95 OutputArea.prototype.bind_events = function () {
95 OutputArea.prototype.bind_events = function () {
96 var that = this;
96 var that = this;
97 this.prompt_overlay.dblclick(function () { that.toggle_output(); });
97 this.prompt_overlay.dblclick(function () { that.toggle_output(); });
98 this.prompt_overlay.click(function () { that.toggle_scroll(); });
98 this.prompt_overlay.click(function () { that.toggle_scroll(); });
99
99
100 this.element.resize(function () {
100 this.element.resize(function () {
101 // FIXME: Firefox on Linux misbehaves, so automatic scrolling is disabled
101 // FIXME: Firefox on Linux misbehaves, so automatic scrolling is disabled
102 if ( IPython.utils.browser[0] === "Firefox" ) {
102 if ( IPython.utils.browser[0] === "Firefox" ) {
103 return;
103 return;
104 }
104 }
105 // maybe scroll output,
105 // maybe scroll output,
106 // if it's grown large enough and hasn't already been scrolled.
106 // if it's grown large enough and hasn't already been scrolled.
107 if ( !that.scrolled && that._should_scroll(OutputArea.auto_scroll_threshold)) {
107 if ( !that.scrolled && that._should_scroll(OutputArea.auto_scroll_threshold)) {
108 that.scroll_area();
108 that.scroll_area();
109 }
109 }
110 });
110 });
111 this.collapse_button.click(function () {
111 this.collapse_button.click(function () {
112 that.expand();
112 that.expand();
113 });
113 });
114 };
114 };
115
115
116
116
117 OutputArea.prototype.collapse = function () {
117 OutputArea.prototype.collapse = function () {
118 if (!this.collapsed) {
118 if (!this.collapsed) {
119 this.element.hide();
119 this.element.hide();
120 this.prompt_overlay.hide();
120 this.prompt_overlay.hide();
121 if (this.element.html()){
121 if (this.element.html()){
122 this.collapse_button.show();
122 this.collapse_button.show();
123 }
123 }
124 this.collapsed = true;
124 this.collapsed = true;
125 }
125 }
126 };
126 };
127
127
128
128
129 OutputArea.prototype.expand = function () {
129 OutputArea.prototype.expand = function () {
130 if (this.collapsed) {
130 if (this.collapsed) {
131 this.collapse_button.hide();
131 this.collapse_button.hide();
132 this.element.show();
132 this.element.show();
133 this.prompt_overlay.show();
133 this.prompt_overlay.show();
134 this.collapsed = false;
134 this.collapsed = false;
135 }
135 }
136 };
136 };
137
137
138
138
139 OutputArea.prototype.toggle_output = function () {
139 OutputArea.prototype.toggle_output = function () {
140 if (this.collapsed) {
140 if (this.collapsed) {
141 this.expand();
141 this.expand();
142 } else {
142 } else {
143 this.collapse();
143 this.collapse();
144 }
144 }
145 };
145 };
146
146
147
147
148 OutputArea.prototype.scroll_area = function () {
148 OutputArea.prototype.scroll_area = function () {
149 this.element.addClass('output_scroll');
149 this.element.addClass('output_scroll');
150 this.prompt_overlay.attr('title', 'click to unscroll output; double click to hide');
150 this.prompt_overlay.attr('title', 'click to unscroll output; double click to hide');
151 this.scrolled = true;
151 this.scrolled = true;
152 };
152 };
153
153
154
154
155 OutputArea.prototype.unscroll_area = function () {
155 OutputArea.prototype.unscroll_area = function () {
156 this.element.removeClass('output_scroll');
156 this.element.removeClass('output_scroll');
157 this.prompt_overlay.attr('title', 'click to scroll output; double click to hide');
157 this.prompt_overlay.attr('title', 'click to scroll output; double click to hide');
158 this.scrolled = false;
158 this.scrolled = false;
159 };
159 };
160
160
161 /**
161 /**
162 * Threshold to trigger autoscroll when the OutputArea is resized,
162 * Threshold to trigger autoscroll when the OutputArea is resized,
163 * typically when new outputs are added.
163 * typically when new outputs are added.
164 *
164 *
165 * Behavior is undefined if autoscroll is lower than minimum_scroll_threshold,
165 * Behavior is undefined if autoscroll is lower than minimum_scroll_threshold,
166 * unless it is < 0, in which case autoscroll will never be triggered
166 * unless it is < 0, in which case autoscroll will never be triggered
167 *
167 *
168 * @property auto_scroll_threshold
168 * @property auto_scroll_threshold
169 * @type Number
169 * @type Number
170 * @default 100
170 * @default 100
171 *
171 *
172 **/
172 **/
173 OutputArea.auto_scroll_threshold = 100;
173 OutputArea.auto_scroll_threshold = 100;
174
174
175
175
176 /**
176 /**
177 * Lower limit (in lines) for OutputArea to be made scrollable. OutputAreas
177 * Lower limit (in lines) for OutputArea to be made scrollable. OutputAreas
178 * shorter than this are never scrolled.
178 * shorter than this are never scrolled.
179 *
179 *
180 * @property minimum_scroll_threshold
180 * @property minimum_scroll_threshold
181 * @type Number
181 * @type Number
182 * @default 20
182 * @default 20
183 *
183 *
184 **/
184 **/
185 OutputArea.minimum_scroll_threshold = 20;
185 OutputArea.minimum_scroll_threshold = 20;
186
186
187
187
188 /**
188 /**
189 *
189 *
190 * Scroll OutputArea if height supperior than a threshold (in lines).
190 * Scroll OutputArea if height supperior than a threshold (in lines).
191 *
191 *
192 * Threshold is a maximum number of lines. If unspecified, defaults to
192 * Threshold is a maximum number of lines. If unspecified, defaults to
193 * OutputArea.minimum_scroll_threshold.
193 * OutputArea.minimum_scroll_threshold.
194 *
194 *
195 * Negative threshold will prevent the OutputArea from ever scrolling.
195 * Negative threshold will prevent the OutputArea from ever scrolling.
196 *
196 *
197 * @method scroll_if_long
197 * @method scroll_if_long
198 *
198 *
199 * @param [lines=20]{Number} Default to 20 if not set,
199 * @param [lines=20]{Number} Default to 20 if not set,
200 * behavior undefined for value of `0`.
200 * behavior undefined for value of `0`.
201 *
201 *
202 **/
202 **/
203 OutputArea.prototype.scroll_if_long = function (lines) {
203 OutputArea.prototype.scroll_if_long = function (lines) {
204 var n = lines | OutputArea.minimum_scroll_threshold;
204 var n = lines | OutputArea.minimum_scroll_threshold;
205 if(n <= 0){
205 if(n <= 0){
206 return
206 return
207 }
207 }
208
208
209 if (this._should_scroll(n)) {
209 if (this._should_scroll(n)) {
210 // only allow scrolling long-enough output
210 // only allow scrolling long-enough output
211 this.scroll_area();
211 this.scroll_area();
212 }
212 }
213 };
213 };
214
214
215
215
216 OutputArea.prototype.toggle_scroll = function () {
216 OutputArea.prototype.toggle_scroll = function () {
217 if (this.scrolled) {
217 if (this.scrolled) {
218 this.unscroll_area();
218 this.unscroll_area();
219 } else {
219 } else {
220 // only allow scrolling long-enough output
220 // only allow scrolling long-enough output
221 this.scroll_if_long();
221 this.scroll_if_long();
222 }
222 }
223 };
223 };
224
224
225
225
226 // typeset with MathJax if MathJax is available
226 // typeset with MathJax if MathJax is available
227 OutputArea.prototype.typeset = function () {
227 OutputArea.prototype.typeset = function () {
228 if (window.MathJax){
228 if (window.MathJax){
229 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
229 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
230 }
230 }
231 };
231 };
232
232
233
233
234 OutputArea.prototype.handle_output = function (msg) {
234 OutputArea.prototype.handle_output = function (msg) {
235 var json = {};
235 var json = {};
236 var msg_type = json.output_type = msg.header.msg_type;
236 var msg_type = json.output_type = msg.header.msg_type;
237 var content = msg.content;
237 var content = msg.content;
238 if (msg_type === "stream") {
238 if (msg_type === "stream") {
239 json.text = content.data;
239 json.text = content.data;
240 json.stream = content.name;
240 json.stream = content.name;
241 } else if (msg_type === "display_data") {
241 } else if (msg_type === "display_data") {
242 json = this.convert_mime_types(json, content.data);
242 json = this.convert_mime_types(json, content.data);
243 json.metadata = this.convert_mime_types({}, content.metadata);
243 json.metadata = this.convert_mime_types({}, content.metadata);
244 } else if (msg_type === "pyout") {
244 } else if (msg_type === "pyout") {
245 json.prompt_number = content.execution_count;
245 json.prompt_number = content.execution_count;
246 json = this.convert_mime_types(json, content.data);
246 json = this.convert_mime_types(json, content.data);
247 json.metadata = this.convert_mime_types({}, content.metadata);
247 json.metadata = this.convert_mime_types({}, content.metadata);
248 } else if (msg_type === "pyerr") {
248 } else if (msg_type === "pyerr") {
249 json.ename = content.ename;
249 json.ename = content.ename;
250 json.evalue = content.evalue;
250 json.evalue = content.evalue;
251 json.traceback = content.traceback;
251 json.traceback = content.traceback;
252 }
252 }
253 // append with dynamic=true
253 // append with dynamic=true
254 this.append_output(json, true);
254 this.append_output(json, true);
255 };
255 };
256
256
257
257
258 OutputArea.prototype.convert_mime_types = function (json, data) {
258 OutputArea.prototype.convert_mime_types = function (json, data) {
259 if (data === undefined) {
259 if (data === undefined) {
260 return json;
260 return json;
261 }
261 }
262 if (data['text/plain'] !== undefined) {
262 if (data['text/plain'] !== undefined) {
263 json.text = data['text/plain'];
263 json.text = data['text/plain'];
264 }
264 }
265 if (data['text/html'] !== undefined) {
265 if (data['text/html'] !== undefined) {
266 json.html = data['text/html'];
266 json.html = data['text/html'];
267 }
267 }
268 if (data['image/svg+xml'] !== undefined) {
268 if (data['image/svg+xml'] !== undefined) {
269 json.svg = data['image/svg+xml'];
269 json.svg = data['image/svg+xml'];
270 }
270 }
271 if (data['image/png'] !== undefined) {
271 if (data['image/png'] !== undefined) {
272 json.png = data['image/png'];
272 json.png = data['image/png'];
273 }
273 }
274 if (data['image/jpeg'] !== undefined) {
274 if (data['image/jpeg'] !== undefined) {
275 json.jpeg = data['image/jpeg'];
275 json.jpeg = data['image/jpeg'];
276 }
276 }
277 if (data['text/latex'] !== undefined) {
277 if (data['text/latex'] !== undefined) {
278 json.latex = data['text/latex'];
278 json.latex = data['text/latex'];
279 }
279 }
280 if (data['application/json'] !== undefined) {
280 if (data['application/json'] !== undefined) {
281 json.json = data['application/json'];
281 json.json = data['application/json'];
282 }
282 }
283 if (data['application/javascript'] !== undefined) {
283 if (data['application/javascript'] !== undefined) {
284 json.javascript = data['application/javascript'];
284 json.javascript = data['application/javascript'];
285 }
285 }
286 return json;
286 return json;
287 };
287 };
288
288
289
289
290 OutputArea.prototype.append_output = function (json, dynamic) {
290 OutputArea.prototype.append_output = function (json, dynamic) {
291 // If dynamic is true, javascript output will be eval'd.
291 // If dynamic is true, javascript output will be eval'd.
292 this.expand();
292 this.expand();
293
293
294 // Clear the output if clear is queued.
294 // Clear the output if clear is queued.
295 var needs_height_reset = false;
295 var needs_height_reset = false;
296 if (this.clear_queued) {
296 if (this.clear_queued) {
297 this.clear_output(false);
297 this.clear_output(false);
298 needs_height_reset = true;
298 needs_height_reset = true;
299 }
299 }
300
300
301 if (json.output_type === 'pyout') {
301 if (json.output_type === 'pyout') {
302 this.append_pyout(json, dynamic);
302 this.append_pyout(json, dynamic);
303 } else if (json.output_type === 'pyerr') {
303 } else if (json.output_type === 'pyerr') {
304 this.append_pyerr(json);
304 this.append_pyerr(json);
305 } else if (json.output_type === 'display_data') {
305 } else if (json.output_type === 'display_data') {
306 this.append_display_data(json, dynamic);
306 this.append_display_data(json, dynamic);
307 } else if (json.output_type === 'stream') {
307 } else if (json.output_type === 'stream') {
308 this.append_stream(json);
308 this.append_stream(json);
309 }
309 }
310 this.outputs.push(json);
310 this.outputs.push(json);
311
311
312 // Only reset the height to automatic if the height is currently
312 // Only reset the height to automatic if the height is currently
313 // fixed (done by wait=True flag on clear_output).
313 // fixed (done by wait=True flag on clear_output).
314 if (needs_height_reset) {
314 if (needs_height_reset) {
315 this.element.height('');
315 this.element.height('');
316 }
316 }
317
317
318 var that = this;
318 var that = this;
319 setTimeout(function(){that.element.trigger('resize');}, 100);
319 setTimeout(function(){that.element.trigger('resize');}, 100);
320 };
320 };
321
321
322
322
323 OutputArea.prototype.create_output_area = function () {
323 OutputArea.prototype.create_output_area = function () {
324 var oa = $("<div/>").addClass("output_area");
324 var oa = $("<div/>").addClass("output_area");
325 if (this.prompt_area) {
325 if (this.prompt_area) {
326 oa.append($('<div/>').addClass('prompt'));
326 oa.append($('<div/>').addClass('prompt'));
327 }
327 }
328 return oa;
328 return oa;
329 };
329 };
330
330
331 OutputArea.prototype._append_javascript_error = function (err, container) {
331 OutputArea.prototype._append_javascript_error = function (err, container) {
332 // display a message when a javascript error occurs in display output
332 // display a message when a javascript error occurs in display output
333 var msg = "Javascript error adding output!"
333 var msg = "Javascript error adding output!"
334 console.log(msg, err);
334 console.log(msg, err);
335 if ( container === undefined ) return;
335 if ( container === undefined ) return;
336 container.append(
336 container.append(
337 $('<div/>').html(msg + "<br/>" +
337 $('<div/>').html(msg + "<br/>" +
338 err.toString() +
338 err.toString() +
339 '<br/>See your browser Javascript console for more details.'
339 '<br/>See your browser Javascript console for more details.'
340 ).addClass('js-error')
340 ).addClass('js-error')
341 );
341 );
342 container.show();
342 container.show();
343 };
343 };
344
344
345 OutputArea.prototype._safe_append = function (toinsert) {
345 OutputArea.prototype._safe_append = function (toinsert) {
346 // safely append an item to the document
346 // safely append an item to the document
347 // this is an object created by user code,
347 // this is an object created by user code,
348 // and may have errors, which should not be raised
348 // and may have errors, which should not be raised
349 // under any circumstances.
349 // under any circumstances.
350 try {
350 try {
351 this.element.append(toinsert);
351 this.element.append(toinsert);
352 } catch(err) {
352 } catch(err) {
353 console.log(err);
353 console.log(err);
354 this._append_javascript_error(err, this.element);
354 this._append_javascript_error(err, this.element);
355 }
355 }
356 };
356 };
357
357
358
358
359 OutputArea.prototype.append_pyout = function (json, dynamic) {
359 OutputArea.prototype.append_pyout = function (json, dynamic) {
360 var n = json.prompt_number || ' ';
360 var n = json.prompt_number || ' ';
361 var toinsert = this.create_output_area();
361 var toinsert = this.create_output_area();
362 if (this.prompt_area) {
362 if (this.prompt_area) {
363 toinsert.find('div.prompt').addClass('output_prompt').html('Out[' + n + ']:');
363 toinsert.find('div.prompt').addClass('output_prompt').html('Out[' + n + ']:');
364 }
364 }
365 this.append_mime_type(json, toinsert, dynamic);
365 this.append_mime_type(json, toinsert, dynamic);
366 this._safe_append(toinsert);
366 this._safe_append(toinsert);
367 // If we just output latex, typeset it.
367 // If we just output latex, typeset it.
368 if ((json.latex !== undefined) || (json.html !== undefined)) {
368 if ((json.latex !== undefined) || (json.html !== undefined)) {
369 this.typeset();
369 this.typeset();
370 }
370 }
371 };
371 };
372
372
373
373
374 OutputArea.prototype.append_pyerr = function (json) {
374 OutputArea.prototype.append_pyerr = function (json) {
375 var tb = json.traceback;
375 var tb = json.traceback;
376 if (tb !== undefined && tb.length > 0) {
376 if (tb !== undefined && tb.length > 0) {
377 var s = '';
377 var s = '';
378 var len = tb.length;
378 var len = tb.length;
379 for (var i=0; i<len; i++) {
379 for (var i=0; i<len; i++) {
380 s = s + tb[i] + '\n';
380 s = s + tb[i] + '\n';
381 }
381 }
382 s = s + '\n';
382 s = s + '\n';
383 var toinsert = this.create_output_area();
383 var toinsert = this.create_output_area();
384 this.append_text(s, {}, toinsert);
384 this.append_text(s, {}, toinsert);
385 this._safe_append(toinsert);
385 this._safe_append(toinsert);
386 }
386 }
387 };
387 };
388
388
389
389
390 OutputArea.prototype.append_stream = function (json) {
390 OutputArea.prototype.append_stream = function (json) {
391 // temporary fix: if stream undefined (json file written prior to this patch),
391 // temporary fix: if stream undefined (json file written prior to this patch),
392 // default to most likely stdout:
392 // default to most likely stdout:
393 if (json.stream == undefined){
393 if (json.stream == undefined){
394 json.stream = 'stdout';
394 json.stream = 'stdout';
395 }
395 }
396 var text = json.text;
396 var text = json.text;
397 var subclass = "output_"+json.stream;
397 var subclass = "output_"+json.stream;
398 if (this.outputs.length > 0){
398 if (this.outputs.length > 0){
399 // have at least one output to consider
399 // have at least one output to consider
400 var last = this.outputs[this.outputs.length-1];
400 var last = this.outputs[this.outputs.length-1];
401 if (last.output_type == 'stream' && json.stream == last.stream){
401 if (last.output_type == 'stream' && json.stream == last.stream){
402 // latest output was in the same stream,
402 // latest output was in the same stream,
403 // so append directly into its pre tag
403 // so append directly into its pre tag
404 // escape ANSI & HTML specials:
404 // escape ANSI & HTML specials:
405 var pre = this.element.find('div.'+subclass).last().find('pre');
405 var pre = this.element.find('div.'+subclass).last().find('pre');
406 var html = utils.fixCarriageReturn(
406 var html = utils.fixCarriageReturn(
407 pre.html() + utils.fixConsole(text));
407 pre.html() + utils.fixConsole(text));
408 pre.html(html);
408 pre.html(html);
409 return;
409 return;
410 }
410 }
411 }
411 }
412
412
413 if (!text.replace("\r", "")) {
413 if (!text.replace("\r", "")) {
414 // text is nothing (empty string, \r, etc.)
414 // text is nothing (empty string, \r, etc.)
415 // so don't append any elements, which might add undesirable space
415 // so don't append any elements, which might add undesirable space
416 return;
416 return;
417 }
417 }
418
418
419 // If we got here, attach a new div
419 // If we got here, attach a new div
420 var toinsert = this.create_output_area();
420 var toinsert = this.create_output_area();
421 this.append_text(text, {}, toinsert, "output_stream "+subclass);
421 this.append_text(text, {}, toinsert, "output_stream "+subclass);
422 this._safe_append(toinsert);
422 this._safe_append(toinsert);
423 };
423 };
424
424
425
425
426 OutputArea.prototype.append_display_data = function (json, dynamic) {
426 OutputArea.prototype.append_display_data = function (json, dynamic) {
427 var toinsert = this.create_output_area();
427 var toinsert = this.create_output_area();
428 this.append_mime_type(json, toinsert, dynamic);
428 this.append_mime_type(json, toinsert, dynamic);
429 this._safe_append(toinsert);
429 this._safe_append(toinsert);
430 // If we just output latex, typeset it.
430 // If we just output latex, typeset it.
431 if ( (json.latex !== undefined) || (json.html !== undefined) ) {
431 if ( (json.latex !== undefined) || (json.html !== undefined) ) {
432 this.typeset();
432 this.typeset();
433 }
433 }
434 };
434 };
435
435
436 OutputArea.display_order = ['javascript','html','latex','svg','png','jpeg','text'];
436 OutputArea.display_order = ['javascript','html','latex','svg','png','jpeg','text'];
437
437
438 OutputArea.prototype.append_mime_type = function (json, element, dynamic) {
438 OutputArea.prototype.append_mime_type = function (json, element, dynamic) {
439 for(var type_i in OutputArea.display_order){
439 for(var type_i in OutputArea.display_order){
440 var type = OutputArea.display_order[type_i];
440 var type = OutputArea.display_order[type_i];
441 if(json[type] != undefined ){
441 if(json[type] != undefined ){
442 var md = {};
442 var md = {};
443 if (json.metadata && json.metadata[type]) {
443 if (json.metadata && json.metadata[type]) {
444 md = json.metadata[type];
444 md = json.metadata[type];
445 };
445 };
446 if(type == 'javascript'){
446 if(type == 'javascript'){
447 if (dynamic) {
447 if (dynamic) {
448 this.append_javascript(json.javascript, md, element, dynamic);
448 this.append_javascript(json.javascript, md, element, dynamic);
449 }
449 }
450 } else {
450 } else {
451 this['append_'+type](json[type], md, element);
451 this['append_'+type](json[type], md, element);
452 }
452 }
453 return;
453 return;
454 }
454 }
455 }
455 }
456 };
456 };
457
457
458
458
459 OutputArea.prototype.append_html = function (html, md, element) {
459 OutputArea.prototype.append_html = function (html, md, element) {
460 var toinsert = $("<div/>").addClass("output_subarea output_html rendered_html");
460 var toinsert = $("<div/>").addClass("output_subarea output_html rendered_html");
461 toinsert.append(html);
461 toinsert.append(html);
462 element.append(toinsert);
462 element.append(toinsert);
463 };
463 };
464
464
465
465
466 OutputArea.prototype.append_javascript = function (js, md, container) {
466 OutputArea.prototype.append_javascript = function (js, md, container) {
467 // We just eval the JS code, element appears in the local scope.
467 // We just eval the JS code, element appears in the local scope.
468 var element = $("<div/>").addClass("output_subarea");
468 var element = $("<div/>").addClass("output_subarea");
469 container.append(element);
469 container.append(element);
470 // Div for js shouldn't be drawn, as it will add empty height to the area.
470 // Div for js shouldn't be drawn, as it will add empty height to the area.
471 container.hide();
471 container.hide();
472 // If the Javascript appends content to `element` that should be drawn, then
472 // If the Javascript appends content to `element` that should be drawn, then
473 // it must also call `container.show()`.
473 // it must also call `container.show()`.
474 try {
474 try {
475 eval(js);
475 eval(js);
476 } catch(err) {
476 } catch(err) {
477 this._append_javascript_error(err, container);
477 this._append_javascript_error(err, container);
478 }
478 }
479 };
479 };
480
480
481
481
482 OutputArea.prototype.append_text = function (data, md, element, extra_class) {
482 OutputArea.prototype.append_text = function (data, md, element, extra_class) {
483 var toinsert = $("<div/>").addClass("output_subarea output_text");
483 var toinsert = $("<div/>").addClass("output_subarea output_text");
484 // escape ANSI & HTML specials in plaintext:
484 // escape ANSI & HTML specials in plaintext:
485 data = utils.fixConsole(data);
485 data = utils.fixConsole(data);
486 data = utils.fixCarriageReturn(data);
486 data = utils.fixCarriageReturn(data);
487 data = utils.autoLinkUrls(data);
487 data = utils.autoLinkUrls(data);
488 if (extra_class){
488 if (extra_class){
489 toinsert.addClass(extra_class);
489 toinsert.addClass(extra_class);
490 }
490 }
491 toinsert.append($("<pre/>").html(data));
491 toinsert.append($("<pre/>").html(data));
492 element.append(toinsert);
492 element.append(toinsert);
493 };
493 };
494
494
495
495
496 OutputArea.prototype.append_svg = function (svg, md, element) {
496 OutputArea.prototype.append_svg = function (svg, md, element) {
497 var toinsert = $("<div/>").addClass("output_subarea output_svg");
497 var toinsert = $("<div/>").addClass("output_subarea output_svg");
498 toinsert.append(svg);
498 toinsert.append(svg);
499 element.append(toinsert);
499 element.append(toinsert);
500 };
500 };
501
501
502
502
503 OutputArea.prototype._dblclick_to_reset_size = function (img) {
503 OutputArea.prototype._dblclick_to_reset_size = function (img) {
504 // schedule wrapping image in resizable after a delay,
504 // schedule wrapping image in resizable after a delay,
505 // so we don't end up calling resize on a zero-size object
505 // so we don't end up calling resize on a zero-size object
506 var that = this;
506 var that = this;
507 setTimeout(function () {
507 setTimeout(function () {
508 var h0 = img.height();
508 var h0 = img.height();
509 var w0 = img.width();
509 var w0 = img.width();
510 if (!(h0 && w0)) {
510 if (!(h0 && w0)) {
511 // zero size, schedule another timeout
511 // zero size, schedule another timeout
512 that._dblclick_to_reset_size(img);
512 that._dblclick_to_reset_size(img);
513 return;
513 return;
514 }
514 }
515 img.resizable({
515 img.resizable({
516 aspectRatio: true,
516 aspectRatio: true,
517 autoHide: true
517 autoHide: true
518 });
518 });
519 img.dblclick(function () {
519 img.dblclick(function () {
520 // resize wrapper & image together for some reason:
520 // resize wrapper & image together for some reason:
521 img.parent().height(h0);
521 img.parent().height(h0);
522 img.height(h0);
522 img.height(h0);
523 img.parent().width(w0);
523 img.parent().width(w0);
524 img.width(w0);
524 img.width(w0);
525 });
525 });
526 }, 250);
526 }, 250);
527 };
527 };
528
528
529
529
530 OutputArea.prototype.append_png = function (png, md, element) {
530 OutputArea.prototype.append_png = function (png, md, element) {
531 var toinsert = $("<div/>").addClass("output_subarea output_png");
531 var toinsert = $("<div/>").addClass("output_subarea output_png");
532 var img = $("<img/>").attr('src','data:image/png;base64,'+png);
532 var img = $("<img/>").attr('src','data:image/png;base64,'+png);
533 if (md['height']) {
533 if (md['height']) {
534 img.attr('height', md['height']);
534 img.attr('height', md['height']);
535 }
535 }
536 if (md['width']) {
536 if (md['width']) {
537 img.attr('width', md['width']);
537 img.attr('width', md['width']);
538 }
538 }
539 this._dblclick_to_reset_size(img);
539 this._dblclick_to_reset_size(img);
540 toinsert.append(img);
540 toinsert.append(img);
541 element.append(toinsert);
541 element.append(toinsert);
542 };
542 };
543
543
544
544
545 OutputArea.prototype.append_jpeg = function (jpeg, md, element) {
545 OutputArea.prototype.append_jpeg = function (jpeg, md, element) {
546 var toinsert = $("<div/>").addClass("output_subarea output_jpeg");
546 var toinsert = $("<div/>").addClass("output_subarea output_jpeg");
547 var img = $("<img/>").attr('src','data:image/jpeg;base64,'+jpeg);
547 var img = $("<img/>").attr('src','data:image/jpeg;base64,'+jpeg);
548 if (md['height']) {
548 if (md['height']) {
549 img.attr('height', md['height']);
549 img.attr('height', md['height']);
550 }
550 }
551 if (md['width']) {
551 if (md['width']) {
552 img.attr('width', md['width']);
552 img.attr('width', md['width']);
553 }
553 }
554 this._dblclick_to_reset_size(img);
554 this._dblclick_to_reset_size(img);
555 toinsert.append(img);
555 toinsert.append(img);
556 element.append(toinsert);
556 element.append(toinsert);
557 };
557 };
558
558
559
559
560 OutputArea.prototype.append_latex = function (latex, md, element) {
560 OutputArea.prototype.append_latex = function (latex, md, element) {
561 // This method cannot do the typesetting because the latex first has to
561 // This method cannot do the typesetting because the latex first has to
562 // be on the page.
562 // be on the page.
563 var toinsert = $("<div/>").addClass("output_subarea output_latex");
563 var toinsert = $("<div/>").addClass("output_subarea output_latex");
564 toinsert.append(latex);
564 toinsert.append(latex);
565 element.append(toinsert);
565 element.append(toinsert);
566 };
566 };
567
567
568 OutputArea.prototype.append_raw_input = function (msg) {
568 OutputArea.prototype.append_raw_input = function (msg) {
569 var that = this;
569 var that = this;
570 this.expand();
570 this.expand();
571 var content = msg.content;
571 var content = msg.content;
572 var area = this.create_output_area();
572 var area = this.create_output_area();
573
573
574 // disable any other raw_inputs, if they are left around
574 // disable any other raw_inputs, if they are left around
575 $("div.output_subarea.raw_input").remove();
575 $("div.output_subarea.raw_input").remove();
576
576
577 area.append(
577 area.append(
578 $("<div/>")
578 $("<div/>")
579 .addClass("box-flex1 output_subarea raw_input")
579 .addClass("box-flex1 output_subarea raw_input")
580 .append(
580 .append(
581 $("<span/>")
581 $("<span/>")
582 .addClass("input_prompt")
582 .addClass("input_prompt")
583 .text(content.prompt)
583 .text(content.prompt)
584 )
584 )
585 .append(
585 .append(
586 $("<input/>")
586 $("<input/>")
587 .addClass("raw_input")
587 .addClass("raw_input")
588 .attr('type', 'text')
588 .attr('type', 'text')
589 .attr("size", 47)
589 .attr("size", 47)
590 .keydown(function (event, ui) {
590 .keydown(function (event, ui) {
591 // make sure we submit on enter,
591 // make sure we submit on enter,
592 // and don't re-execute the *cell* on shift-enter
592 // and don't re-execute the *cell* on shift-enter
593 if (event.which === utils.keycodes.ENTER) {
593 if (event.which === utils.keycodes.ENTER) {
594 that._submit_raw_input();
594 that._submit_raw_input();
595 return false;
595 return false;
596 }
596 }
597 })
597 })
598 )
598 )
599 );
599 );
600 this.element.append(area);
600 this.element.append(area);
601 // weirdly need double-focus now,
601 // weirdly need double-focus now,
602 // otherwise only the cell will be focused
602 // otherwise only the cell will be focused
603 area.find("input.raw_input").focus().focus();
603 area.find("input.raw_input").focus().focus();
604 }
604 }
605 OutputArea.prototype._submit_raw_input = function (evt) {
605 OutputArea.prototype._submit_raw_input = function (evt) {
606 var container = this.element.find("div.raw_input");
606 var container = this.element.find("div.raw_input");
607 var theprompt = container.find("span.input_prompt");
607 var theprompt = container.find("span.input_prompt");
608 var theinput = container.find("input.raw_input");
608 var theinput = container.find("input.raw_input");
609 var value = theinput.val();
609 var value = theinput.val();
610 var content = {
610 var content = {
611 output_type : 'stream',
611 output_type : 'stream',
612 name : 'stdout',
612 name : 'stdout',
613 text : theprompt.text() + value + '\n'
613 text : theprompt.text() + value + '\n'
614 }
614 }
615 // remove form container
615 // remove form container
616 container.parent().remove();
616 container.parent().remove();
617 // replace with plaintext version in stdout
617 // replace with plaintext version in stdout
618 this.append_output(content, false);
618 this.append_output(content, false);
619 $([IPython.events]).trigger('send_input_reply.Kernel', value);
619 $([IPython.events]).trigger('send_input_reply.Kernel', value);
620 }
620 }
621
621
622
622
623 OutputArea.prototype.handle_clear_output = function (msg) {
623 OutputArea.prototype.handle_clear_output = function (msg) {
624 this.clear_output(msg.content.wait);
624 this.clear_output(msg.content.wait);
625 };
625 };
626
626
627
627
628 OutputArea.prototype.clear_output = function(wait) {
628 OutputArea.prototype.clear_output = function(wait) {
629 if (wait) {
629 if (wait) {
630
630
631 // If a clear is queued, clear before adding another to the queue.
631 // If a clear is queued, clear before adding another to the queue.
632 if (this.clear_queued) {
632 if (this.clear_queued) {
633 this.clear_output(false);
633 this.clear_output(false);
634 };
634 };
635
635
636 this.clear_queued = true;
636 this.clear_queued = true;
637 } else {
637 } else {
638
638
639 // Fix the output div's height if the clear_output is waiting for
639 // Fix the output div's height if the clear_output is waiting for
640 // new output (it is being used in an animation).
640 // new output (it is being used in an animation).
641 if (this.clear_queued) {
641 if (this.clear_queued) {
642 var height = this.element.height();
642 var height = this.element.height();
643 this.element.height(height);
643 this.element.height(height);
644 this.clear_queued = false;
644 this.clear_queued = false;
645 }
645 }
646
646
647 // clear all, no need for logic
647 // clear all, no need for logic
648 this.element.html("");
648 this.element.html("");
649 this.outputs = [];
649 this.outputs = [];
650 this.unscroll_area();
650 this.unscroll_area();
651 return;
651 return;
652 };
652 };
653 };
653 };
654
654
655
655
656 // JSON serialization
656 // JSON serialization
657
657
658 OutputArea.prototype.fromJSON = function (outputs) {
658 OutputArea.prototype.fromJSON = function (outputs) {
659 var len = outputs.length;
659 var len = outputs.length;
660 for (var i=0; i<len; i++) {
660 for (var i=0; i<len; i++) {
661 // append with dynamic=false.
661 // append with dynamic=false.
662 this.append_output(outputs[i], false);
662 this.append_output(outputs[i], false);
663 }
663 }
664 };
664 };
665
665
666
666
667 OutputArea.prototype.toJSON = function () {
667 OutputArea.prototype.toJSON = function () {
668 var outputs = [];
668 var outputs = [];
669 var len = this.outputs.length;
669 var len = this.outputs.length;
670 for (var i=0; i<len; i++) {
670 for (var i=0; i<len; i++) {
671 outputs[i] = this.outputs[i];
671 outputs[i] = this.outputs[i];
672 }
672 }
673 return outputs;
673 return outputs;
674 };
674 };
675
675
676
676
677 IPython.OutputArea = OutputArea;
677 IPython.OutputArea = OutputArea;
678
678
679 return IPython;
679 return IPython;
680
680
681 }(IPython));
681 }(IPython));
@@ -1,109 +1,111 b''
1 /* Css for the metadata edit area */
1 /* Css for the metadata edit area */
2
2
3
3
4 .celltoolbar {
4 .celltoolbar {
5 border: thin solid #CFCFCF;
5 border: thin solid #CFCFCF;
6 border-bottom: none;
6 border-bottom: none;
7 background : #EEE;
7 background : #EEE;
8 border-top-right-radius: 3px;
8 border-top-right-radius: 3px;
9 border-top-left-radius: 3px;
9 border-top-left-radius: 3px;
10 width:100%;
10 width:100%;
11 -webkit-box-pack: end;
11 -webkit-box-pack: end;
12 height:22px;
12 height:22px;
13 .hbox();
14 .reverse();
13 }
15 }
14
16
15
17
16 .no_input_radius {
18 .no_input_radius {
17 border-top-right-radius: 0px;
19 border-top-right-radius: 0px;
18 border-top-left-radius: 0px;
20 border-top-left-radius: 0px;
19 }
21 }
20
22
21 .text_cell .ctb_prompt {
23 .text_cell .ctb_prompt {
22 display: none;
24 display: none;
23 }
25 }
24
26
25 .code_cell .ctb_prompt {
27 .code_cell .ctb_prompt {
26 display: block;
28 display: block;
27 }
29 }
28
30
29 .ctb_hideshow {
31 .ctb_hideshow {
30 display:none;
32 display:none;
31 vertical-align:bottom;
33 vertical-align:bottom;
32 padding-right: 2px;
34 padding-right: 2px;
33 }
35 }
34
36
35 .celltoolbar > div {
37 .celltoolbar > div {
36 padding-top: 0px;
38 padding-top: 0px;
37 }
39 }
38
40
39 .ctb_area {
41 .ctb_area {
40 margin:0;
42 margin:0;
41 padding:0;
43 padding:0;
42 width:100%;
44 width:100%;
43
45
44 }
46 }
45
47
46
48
47 /*ctb_show is added to either body or the ctb_hideshow div to show
49 /*ctb_show is added to either body or the ctb_hideshow div to show
48 all or one cell's toolbars.
50 all or one cell's toolbars.
49 */
51 */
50 .ctb_show.ctb_hideshow, .ctb_show .ctb_hideshow {
52 .ctb_show.ctb_hideshow, .ctb_show .ctb_hideshow {
51 display:block;
53 display:block;
52 }
54 }
53
55
54 .ctb_show .input_area,
56 .ctb_show .input_area,
55 .ctb_show .ctb_hideshow + div.text_cell_input {
57 .ctb_show .ctb_hideshow + div.text_cell_input {
56 border-top-right-radius: 0px;
58 border-top-right-radius: 0px;
57 border-top-left-radius: 0px;
59 border-top-left-radius: 0px;
58 }
60 }
59
61
60 .ctb_show > .celltoolbar {
62 .ctb_show > .celltoolbar {
61 border-bottom-right-radius: 0px;
63 border-bottom-right-radius: 0px;
62 border-bottom-left-radius: 0px;
64 border-bottom-left-radius: 0px;
63 }
65 }
64
66
65 .button_container {
67 .button_container {
66 margin-top:0;
68 margin-top:0;
67 margin-bottom:0;
69 margin-bottom:0;
68 }
70 }
69
71
70
72
71 .ui-button {
73 .ui-button {
72 min-width:30px;
74 min-width:30px;
73 }
75 }
74 .celltoolbar .button_container select {
76 .celltoolbar .button_container select {
75 margin: 10px;
77 margin: 10px;
76 margin-top: 1px;
78 margin-top: 1px;
77 margin-bottom: 0px;
79 margin-bottom: 0px;
78 padding:0;
80 padding:0;
79 font-size: 87%;
81 font-size: 87%;
80 width:auto;
82 width:auto;
81 display:inline-block;
83 display:inline-block;
82 height:18px;
84 height:18px;
83 line-height:18px;
85 line-height:18px;
84 vertical-align:top;
86 vertical-align:top;
85 }
87 }
86
88
87 .celltoolbar label{
89 .celltoolbar label{
88 display:inline-block;
90 display:inline-block;
89 height:15px;
91 height:15px;
90 line-height:15px;
92 line-height:15px;
91 vertical-align:top;
93 vertical-align:top;
92 }
94 }
93
95
94 .celltoolbar label span {
96 .celltoolbar label span {
95 font-size: 85%;
97 font-size: 85%;
96 }
98 }
97
99
98 .celltoolbar input[type=checkbox] {
100 .celltoolbar input[type=checkbox] {
99 margin: 0px;
101 margin: 0px;
100 margin-left: 4px;
102 margin-left: 4px;
101 margin-right: 4px;
103 margin-right: 4px;
102 }
104 }
103
105
104
106
105 .celltoolbar .ui-button {
107 .celltoolbar .ui-button {
106 border: none;
108 border: none;
107 vertical-align:top;
109 vertical-align:top;
108 height:20px;
110 height:20px;
109 }
111 }
@@ -1,115 +1,119 b''
1 /* This class is the outer container of all output sections. */
1 /* This class is the outer container of all output sections. */
2 div.output_area {
2 div.output_area {
3 padding: 0px;
3 padding: 0px;
4 page-break-inside: avoid;
4 page-break-inside: avoid;
5 .hbox();
5 .hbox();
6
6
7 .MathJax_Display {
7 .MathJax_Display {
8 // Inside a CodeCell, elements are left justified
8 // Inside a CodeCell, elements are left justified
9 text-align: left !important;
9 text-align: left !important;
10 }
10 }
11
11
12 .rendered_html {
12 .rendered_html {
13 // Inside a CodeCell, elements are left justified
13 // Inside a CodeCell, elements are left justified
14 table {
14 table {
15 margin-left: 0;
15 margin-left: 0;
16 margin-right: 0;
16 margin-right: 0;
17 }
17 }
18
18
19 img {
19 img {
20 margin-left: 0;
20 margin-left: 0;
21 margin-right: 0;
21 margin-right: 0;
22 }
22 }
23 }
23 }
24 }
24 }
25
25
26
26
27 /* This is needed to protect the pre formating from global settings such
27 /* This is needed to protect the pre formating from global settings such
28 as that of bootstrap */
28 as that of bootstrap */
29 .output {
30 .vbox();
31 }
32
29 div.output_area pre {
33 div.output_area pre {
30 font-family: @monoFontFamily;
34 font-family: @monoFontFamily;
31 margin: 0;
35 margin: 0;
32 padding: 0;
36 padding: 0;
33 border: 0;
37 border: 0;
34 font-size: 100%;
38 font-size: 100%;
35 vertical-align: baseline;
39 vertical-align: baseline;
36 color: black;
40 color: black;
37 background-color: transparent;
41 background-color: transparent;
38 .border-radius(0);
42 .border-radius(0);
39 line-height: inherit;
43 line-height: inherit;
40 }
44 }
41
45
42 /* This class is for the output subarea inside the output_area and after
46 /* This class is for the output subarea inside the output_area and after
43 the prompt div. */
47 the prompt div. */
44 div.output_subarea {
48 div.output_subarea {
45 padding: 0.44em 0.4em 0.4em 1px;
49 padding: 0.44em 0.4em 0.4em 1px;
46 margin-left: 6px;
50 margin-left: 6px;
47 .box-flex1();
51 .box-flex1();
48 }
52 }
49
53
50 /* The rest of the output_* classes are for special styling of the different
54 /* The rest of the output_* classes are for special styling of the different
51 output types */
55 output types */
52
56
53 /* all text output has this class: */
57 /* all text output has this class: */
54 div.output_text {
58 div.output_text {
55 text-align: left;
59 text-align: left;
56 color: @textColor;
60 color: @textColor;
57 font-family: @monoFontFamily;
61 font-family: @monoFontFamily;
58 /* This has to match that of the the CodeMirror class line-height below */
62 /* This has to match that of the the CodeMirror class line-height below */
59 line-height: @code_line_height;
63 line-height: @code_line_height;
60 }
64 }
61
65
62 /* stdout/stderr are 'text' as well as 'stream', but pyout/pyerr are *not* streams */
66 /* stdout/stderr are 'text' as well as 'stream', but pyout/pyerr are *not* streams */
63 div.output_stream {
67 div.output_stream {
64 padding-top: 0.0em;
68 padding-top: 0.0em;
65 padding-bottom: 0.0em;
69 padding-bottom: 0.0em;
66 }
70 }
67 div.output_stdout {
71 div.output_stdout {
68 }
72 }
69 div.output_stderr {
73 div.output_stderr {
70 background: #fdd; /* very light red background for stderr */
74 background: #fdd; /* very light red background for stderr */
71 }
75 }
72
76
73 div.output_latex {
77 div.output_latex {
74 text-align: left;
78 text-align: left;
75 }
79 }
76
80
77 div.output_html {
81 div.output_html {
78 }
82 }
79
83
80 div.output_png {
84 div.output_png {
81 }
85 }
82
86
83 div.output_jpeg {
87 div.output_jpeg {
84 }
88 }
85
89
86 .js-error {
90 .js-error {
87 color: darkred;
91 color: darkred;
88 }
92 }
89
93
90 /* raw_input styles */
94 /* raw_input styles */
91
95
92 div.raw_input {
96 div.raw_input {
93 padding-top: 0px;
97 padding-top: 0px;
94 padding-bottom: 0px;
98 padding-bottom: 0px;
95 height: 1em;
99 height: 1em;
96 line-height: 1em;
100 line-height: 1em;
97 font-family: @monoFontFamily;
101 font-family: @monoFontFamily;
98 }
102 }
99 span.input_prompt {
103 span.input_prompt {
100 font-family: inherit;
104 font-family: inherit;
101 }
105 }
102 input.raw_input {
106 input.raw_input {
103 font-family: inherit;
107 font-family: inherit;
104 font-size: inherit;
108 font-size: inherit;
105 color: inherit;
109 color: inherit;
106 width: auto;
110 width: auto;
107 margin: -2px 0px 0px 1px;
111 margin: -2px 0px 0px 1px;
108 padding-left: 1px;
112 padding-left: 1px;
109 padding-top: 2px;
113 padding-top: 2px;
110 height: 1em;
114 height: 1em;
111 }
115 }
112
116
113 p.p-space {
117 p.p-space {
114 margin-bottom: 10px;
118 margin-bottom: 10px;
115 } No newline at end of file
119 }
@@ -1,148 +1,148 b''
1 {%- extends 'display_priority.tpl' -%}
1 {%- extends 'display_priority.tpl' -%}
2
2
3
3
4 {% block codecell %}
4 {% block codecell %}
5 <div class="cell border-box-sizing code_cell vbox">
5 <div class="cell border-box-sizing code_cell">
6 {{ super() }}
6 {{ super() }}
7 </div>
7 </div>
8 {%- endblock codecell %}
8 {%- endblock codecell %}
9
9
10 {% block input_group -%}
10 {% block input_group -%}
11 <div class="input">
11 <div class="input">
12 {{ super() }}
12 {{ super() }}
13 </div>
13 </div>
14 {% endblock input_group %}
14 {% endblock input_group %}
15
15
16 {% block output_group %}
16 {% block output_group %}
17 <div class="output_wrapper">
17 <div class="output_wrapper">
18 <div class="output vbox">
18 <div class="output">
19 {{ super() }}
19 {{ super() }}
20 </div>
20 </div>
21 </div>
21 </div>
22 {% endblock output_group %}
22 {% endblock output_group %}
23
23
24 {% block in_prompt -%}
24 {% block in_prompt -%}
25 <div class="prompt input_prompt">
25 <div class="prompt input_prompt">
26 In&nbsp;[{{ cell.prompt_number }}]:
26 In&nbsp;[{{ cell.prompt_number }}]:
27 </div>
27 </div>
28 {%- endblock in_prompt %}
28 {%- endblock in_prompt %}
29
29
30 {#
30 {#
31 output_prompt doesn't do anything in HTML,
31 output_prompt doesn't do anything in HTML,
32 because there is a prompt div in each output area (see output block)
32 because there is a prompt div in each output area (see output block)
33 #}
33 #}
34 {% block output_prompt %}
34 {% block output_prompt %}
35 {% endblock output_prompt %}
35 {% endblock output_prompt %}
36
36
37 {% block input %}
37 {% block input %}
38 <div class="input_area box-flex1">
38 <div class="input_area box-flex1">
39 {{ cell.input | highlight2html(metadata=cell.metadata) }}
39 {{ cell.input | highlight2html(metadata=cell.metadata) }}
40 </div>
40 </div>
41 {%- endblock input %}
41 {%- endblock input %}
42
42
43 {% block output %}
43 {% block output %}
44 <div class="output_area">
44 <div class="output_area">
45 {%- if output.output_type == 'pyout' -%}
45 {%- if output.output_type == 'pyout' -%}
46 <div class="prompt output_prompt">
46 <div class="prompt output_prompt">
47 Out[{{ cell.prompt_number }}]:
47 Out[{{ cell.prompt_number }}]:
48 {%- else -%}
48 {%- else -%}
49 <div class="prompt">
49 <div class="prompt">
50 {%- endif -%}
50 {%- endif -%}
51 </div>
51 </div>
52 {{ super() }}
52 {{ super() }}
53 </div>
53 </div>
54 {% endblock output %}
54 {% endblock output %}
55
55
56 {% block markdowncell scoped %}
56 {% block markdowncell scoped %}
57 <div class="text_cell_render border-box-sizing rendered_html">
57 <div class="text_cell_render border-box-sizing rendered_html">
58 {{ cell.source | markdown2html | strip_files_prefix }}
58 {{ cell.source | markdown2html | strip_files_prefix }}
59 </div>
59 </div>
60 {%- endblock markdowncell %}
60 {%- endblock markdowncell %}
61
61
62 {% block headingcell scoped %}
62 {% block headingcell scoped %}
63 <div class="text_cell_render border-box-sizing rendered_html">
63 <div class="text_cell_render border-box-sizing rendered_html">
64 {{ ("#" * cell.level + cell.source) | replace('\n', ' ') | markdown2html | strip_files_prefix | add_anchor }}
64 {{ ("#" * cell.level + cell.source) | replace('\n', ' ') | markdown2html | strip_files_prefix | add_anchor }}
65 </div>
65 </div>
66 {% endblock headingcell %}
66 {% endblock headingcell %}
67
67
68 {% block rawcell scoped %}
68 {% block rawcell scoped %}
69 {{ cell.source }}
69 {{ cell.source }}
70 {% endblock rawcell %}
70 {% endblock rawcell %}
71
71
72 {% block unknowncell scoped %}
72 {% block unknowncell scoped %}
73 unknown type {{ cell.type }}
73 unknown type {{ cell.type }}
74 {% endblock unknowncell %}
74 {% endblock unknowncell %}
75
75
76 {% block pyout -%}
76 {% block pyout -%}
77 <div class="box-flex1 output_subarea output_pyout">
77 <div class="box-flex1 output_subarea output_pyout">
78 {% block data_priority scoped %}
78 {% block data_priority scoped %}
79 {{ super() }}
79 {{ super() }}
80 {% endblock %}
80 {% endblock %}
81 </div>
81 </div>
82 {%- endblock pyout %}
82 {%- endblock pyout %}
83
83
84 {% block stream_stdout -%}
84 {% block stream_stdout -%}
85 <div class="box-flex1 output_subarea output_stream output_stdout">
85 <div class="box-flex1 output_subarea output_stream output_stdout">
86 <pre>
86 <pre>
87 {{ output.text | ansi2html }}
87 {{ output.text | ansi2html }}
88 </pre>
88 </pre>
89 </div>
89 </div>
90 {%- endblock stream_stdout %}
90 {%- endblock stream_stdout %}
91
91
92 {% block stream_stderr -%}
92 {% block stream_stderr -%}
93 <div class="box-flex1 output_subarea output_stream output_stderr">
93 <div class="box-flex1 output_subarea output_stream output_stderr">
94 <pre>
94 <pre>
95 {{ output.text | ansi2html }}
95 {{ output.text | ansi2html }}
96 </pre>
96 </pre>
97 </div>
97 </div>
98 {%- endblock stream_stderr %}
98 {%- endblock stream_stderr %}
99
99
100 {% block data_svg -%}
100 {% block data_svg -%}
101 {{ output.svg }}
101 {{ output.svg }}
102 {%- endblock data_svg %}
102 {%- endblock data_svg %}
103
103
104 {% block data_html -%}
104 {% block data_html -%}
105 <div class="output_html rendered_html">
105 <div class="output_html rendered_html">
106 {{ output.html }}
106 {{ output.html }}
107 </div>
107 </div>
108 {%- endblock data_html %}
108 {%- endblock data_html %}
109
109
110 {% block data_png %}
110 {% block data_png %}
111 <img src="data:image/png;base64,{{ output.png }}">
111 <img src="data:image/png;base64,{{ output.png }}">
112 {%- endblock data_png %}
112 {%- endblock data_png %}
113
113
114 {% block data_jpg %}
114 {% block data_jpg %}
115 <img src="data:image/jpeg;base64,{{ output.jpeg }}">
115 <img src="data:image/jpeg;base64,{{ output.jpeg }}">
116 {%- endblock data_jpg %}
116 {%- endblock data_jpg %}
117
117
118 {% block data_latex %}
118 {% block data_latex %}
119 {{ output.latex }}
119 {{ output.latex }}
120 {%- endblock data_latex %}
120 {%- endblock data_latex %}
121
121
122 {% block pyerr -%}
122 {% block pyerr -%}
123 <div class="box-flex1 output_subarea output_pyerr">
123 <div class="box-flex1 output_subarea output_pyerr">
124 <pre>{{ super() }}</pre>
124 <pre>{{ super() }}</pre>
125 </div>
125 </div>
126 {%- endblock pyerr %}
126 {%- endblock pyerr %}
127
127
128 {%- block traceback_line %}
128 {%- block traceback_line %}
129 {{ line | ansi2html }}
129 {{ line | ansi2html }}
130 {%- endblock traceback_line %}
130 {%- endblock traceback_line %}
131
131
132 {%- block data_text %}
132 {%- block data_text %}
133 <pre>
133 <pre>
134 {{ output.text | ansi2html }}
134 {{ output.text | ansi2html }}
135 </pre>
135 </pre>
136 {%- endblock -%}
136 {%- endblock -%}
137
137
138 {%- block data_javascript %}
138 {%- block data_javascript %}
139 <script type="text/javascript">
139 <script type="text/javascript">
140 {{ output.javascript }}
140 {{ output.javascript }}
141 </script>
141 </script>
142 {%- endblock -%}
142 {%- endblock -%}
143
143
144 {%- block display_data scoped -%}
144 {%- block display_data scoped -%}
145 <div class="box-flex1 output_subarea output_display_data">
145 <div class="box-flex1 output_subarea output_display_data">
146 {{ super() }}
146 {{ super() }}
147 </div>
147 </div>
148 {%- endblock display_data -%}
148 {%- endblock display_data -%}
General Comments 0
You need to be logged in to leave comments. Login now