##// END OF EJS Templates
display order in output area configurable
Matthias BUSSONNIER -
Show More
@@ -1,559 +1,556 b''
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008-2011 The IPython Development Team
2 // Copyright (C) 2008-2011 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 var IPython = (function (IPython) {
12 var IPython = (function (IPython) {
13 "use strict";
13 "use strict";
14
14
15 var utils = IPython.utils;
15 var utils = IPython.utils;
16
16
17 var OutputArea = function (selector, prompt_area) {
17 var OutputArea = function (selector, prompt_area) {
18 this.selector = selector;
18 this.selector = selector;
19 this.wrapper = $(selector);
19 this.wrapper = $(selector);
20 this.outputs = [];
20 this.outputs = [];
21 this.collapsed = false;
21 this.collapsed = false;
22 this.scrolled = false;
22 this.scrolled = false;
23 this.clear_out_timeout = null;
23 this.clear_out_timeout = null;
24 if (prompt_area === undefined) {
24 if (prompt_area === undefined) {
25 this.prompt_area = true;
25 this.prompt_area = true;
26 } else {
26 } else {
27 this.prompt_area = prompt_area;
27 this.prompt_area = prompt_area;
28 };
28 };
29 this.create_elements();
29 this.create_elements();
30 this.style();
30 this.style();
31 this.bind_events();
31 this.bind_events();
32 };
32 };
33
33
34 OutputArea.prototype.create_elements = function () {
34 OutputArea.prototype.create_elements = function () {
35 this.element = $("<div/>");
35 this.element = $("<div/>");
36 this.collapse_button = $("<div/>");
36 this.collapse_button = $("<div/>");
37 this.prompt_overlay = $("<div/>");
37 this.prompt_overlay = $("<div/>");
38 this.wrapper.append(this.prompt_overlay);
38 this.wrapper.append(this.prompt_overlay);
39 this.wrapper.append(this.element);
39 this.wrapper.append(this.element);
40 this.wrapper.append(this.collapse_button);
40 this.wrapper.append(this.collapse_button);
41 };
41 };
42
42
43
43
44 OutputArea.prototype.style = function () {
44 OutputArea.prototype.style = function () {
45 this.collapse_button.hide();
45 this.collapse_button.hide();
46 this.prompt_overlay.hide();
46 this.prompt_overlay.hide();
47
47
48 this.wrapper.addClass('output_wrapper');
48 this.wrapper.addClass('output_wrapper');
49 this.element.addClass('output vbox');
49 this.element.addClass('output vbox');
50
50
51 this.collapse_button.button();
51 this.collapse_button.button();
52 this.collapse_button.addClass('output_collapsed vbox');
52 this.collapse_button.addClass('output_collapsed vbox');
53 this.collapse_button.attr('title', 'click to expand outout');
53 this.collapse_button.attr('title', 'click to expand outout');
54 this.collapse_button.html('. . .');
54 this.collapse_button.html('. . .');
55
55
56 this.prompt_overlay.addClass('out_prompt_overlay prompt');
56 this.prompt_overlay.addClass('out_prompt_overlay prompt');
57 this.prompt_overlay.attr('title', 'click to expand outout; double click to hide output');
57 this.prompt_overlay.attr('title', 'click to expand outout; double click to hide output');
58
58
59 this.collapse();
59 this.collapse();
60 };
60 };
61
61
62
62
63 OutputArea.prototype._should_scroll = function (lines) {
63 OutputArea.prototype._should_scroll = function (lines) {
64 if (!lines) {
64 if (!lines) {
65 lines = 100;
65 lines = 100;
66 }
66 }
67 // line-height from http://stackoverflow.com/questions/1185151
67 // line-height from http://stackoverflow.com/questions/1185151
68 var fontSize = this.element.css('font-size');
68 var fontSize = this.element.css('font-size');
69 var lineHeight = Math.floor(parseInt(fontSize.replace('px','')) * 1.5);
69 var lineHeight = Math.floor(parseInt(fontSize.replace('px','')) * 1.5);
70
70
71 return (this.element.height() > lines * lineHeight);
71 return (this.element.height() > lines * lineHeight);
72 };
72 };
73
73
74
74
75 OutputArea.prototype.bind_events = function () {
75 OutputArea.prototype.bind_events = function () {
76 var that = this;
76 var that = this;
77 this.prompt_overlay.dblclick(function () { that.toggle_output(); });
77 this.prompt_overlay.dblclick(function () { that.toggle_output(); });
78 this.prompt_overlay.click(function () { that.toggle_scroll(); });
78 this.prompt_overlay.click(function () { that.toggle_scroll(); });
79
79
80 this.element.resize(function () {
80 this.element.resize(function () {
81 // FIXME: Firefox on Linux misbehaves, so automatic scrolling is disabled
81 // FIXME: Firefox on Linux misbehaves, so automatic scrolling is disabled
82 if ( IPython.utils.browser[0] === "Firefox" ) {
82 if ( IPython.utils.browser[0] === "Firefox" ) {
83 return;
83 return;
84 }
84 }
85 // maybe scroll output,
85 // maybe scroll output,
86 // if it's grown large enough and hasn't already been scrolled.
86 // if it's grown large enough and hasn't already been scrolled.
87 if ( !that.scrolled && that._should_scroll()) {
87 if ( !that.scrolled && that._should_scroll()) {
88 that.scroll_area();
88 that.scroll_area();
89 }
89 }
90 });
90 });
91 this.collapse_button.click(function () {
91 this.collapse_button.click(function () {
92 that.expand();
92 that.expand();
93 });
93 });
94 this.collapse_button.hover(function () {
94 this.collapse_button.hover(function () {
95 $(this).addClass("ui-state-hover");
95 $(this).addClass("ui-state-hover");
96 }, function () {
96 }, function () {
97 $(this).removeClass("ui-state-hover");
97 $(this).removeClass("ui-state-hover");
98 });
98 });
99 };
99 };
100
100
101
101
102 OutputArea.prototype.collapse = function () {
102 OutputArea.prototype.collapse = function () {
103 if (!this.collapsed) {
103 if (!this.collapsed) {
104 this.element.hide();
104 this.element.hide();
105 this.prompt_overlay.hide();
105 this.prompt_overlay.hide();
106 if (this.element.html()){
106 if (this.element.html()){
107 this.collapse_button.show();
107 this.collapse_button.show();
108 }
108 }
109 this.collapsed = true;
109 this.collapsed = true;
110 };
110 };
111 };
111 };
112
112
113
113
114 OutputArea.prototype.expand = function () {
114 OutputArea.prototype.expand = function () {
115 if (this.collapsed) {
115 if (this.collapsed) {
116 this.collapse_button.hide();
116 this.collapse_button.hide();
117 this.element.show();
117 this.element.show();
118 this.prompt_overlay.show();
118 this.prompt_overlay.show();
119 this.collapsed = false;
119 this.collapsed = false;
120 };
120 };
121 };
121 };
122
122
123
123
124 OutputArea.prototype.toggle_output = function () {
124 OutputArea.prototype.toggle_output = function () {
125 if (this.collapsed) {
125 if (this.collapsed) {
126 this.expand();
126 this.expand();
127 } else {
127 } else {
128 this.collapse();
128 this.collapse();
129 };
129 };
130 };
130 };
131
131
132
132
133 OutputArea.prototype.scroll_area = function () {
133 OutputArea.prototype.scroll_area = function () {
134 this.element.addClass('output_scroll');
134 this.element.addClass('output_scroll');
135 this.prompt_overlay.attr('title', 'click to unscroll output; double click to hide');
135 this.prompt_overlay.attr('title', 'click to unscroll output; double click to hide');
136 this.scrolled = true;
136 this.scrolled = true;
137 };
137 };
138
138
139
139
140 OutputArea.prototype.unscroll_area = function () {
140 OutputArea.prototype.unscroll_area = function () {
141 this.element.removeClass('output_scroll');
141 this.element.removeClass('output_scroll');
142 this.prompt_overlay.attr('title', 'click to scroll output; double click to hide');
142 this.prompt_overlay.attr('title', 'click to scroll output; double click to hide');
143 this.scrolled = false;
143 this.scrolled = false;
144 };
144 };
145
145
146
146
147 OutputArea.prototype.scroll_if_long = function (lines) {
147 OutputArea.prototype.scroll_if_long = function (lines) {
148 if (this._should_scroll(lines)) {
148 if (this._should_scroll(lines)) {
149 // only allow scrolling long-enough output
149 // only allow scrolling long-enough output
150 this.scroll_area();
150 this.scroll_area();
151 };
151 };
152 };
152 };
153
153
154
154
155 OutputArea.prototype.toggle_scroll = function () {
155 OutputArea.prototype.toggle_scroll = function () {
156 if (this.scrolled) {
156 if (this.scrolled) {
157 this.unscroll_area();
157 this.unscroll_area();
158 } else {
158 } else {
159 // only allow scrolling long-enough output
159 // only allow scrolling long-enough output
160 this.scroll_if_long(20);
160 this.scroll_if_long(20);
161 };
161 };
162 };
162 };
163
163
164
164
165 // typeset with MathJax if MathJax is available
165 // typeset with MathJax if MathJax is available
166 OutputArea.prototype.typeset = function () {
166 OutputArea.prototype.typeset = function () {
167 if (window.MathJax){
167 if (window.MathJax){
168 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
168 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
169 }
169 }
170 };
170 };
171
171
172
172
173 OutputArea.prototype.handle_output = function (msg_type, content) {
173 OutputArea.prototype.handle_output = function (msg_type, content) {
174 var json = {};
174 var json = {};
175 json.output_type = msg_type;
175 json.output_type = msg_type;
176 if (msg_type === "stream") {
176 if (msg_type === "stream") {
177 json.text = content.data;
177 json.text = content.data;
178 json.stream = content.name;
178 json.stream = content.name;
179 } else if (msg_type === "display_data") {
179 } else if (msg_type === "display_data") {
180 json = this.convert_mime_types(json, content.data);
180 json = this.convert_mime_types(json, content.data);
181 } else if (msg_type === "pyout") {
181 } else if (msg_type === "pyout") {
182 json.prompt_number = content.execution_count;
182 json.prompt_number = content.execution_count;
183 json = this.convert_mime_types(json, content.data);
183 json = this.convert_mime_types(json, content.data);
184 } else if (msg_type === "pyerr") {
184 } else if (msg_type === "pyerr") {
185 json.ename = content.ename;
185 json.ename = content.ename;
186 json.evalue = content.evalue;
186 json.evalue = content.evalue;
187 json.traceback = content.traceback;
187 json.traceback = content.traceback;
188 };
188 };
189 // append with dynamic=true
189 // append with dynamic=true
190 this.append_output(json, true);
190 this.append_output(json, true);
191 };
191 };
192
192
193
193
194 OutputArea.prototype.convert_mime_types = function (json, data) {
194 OutputArea.prototype.convert_mime_types = function (json, data) {
195 if (data['text/plain'] !== undefined) {
195 if (data['text/plain'] !== undefined) {
196 json.text = data['text/plain'];
196 json.text = data['text/plain'];
197 };
197 };
198 if (data['text/html'] !== undefined) {
198 if (data['text/html'] !== undefined) {
199 json.html = data['text/html'];
199 json.html = data['text/html'];
200 };
200 };
201 if (data['image/svg+xml'] !== undefined) {
201 if (data['image/svg+xml'] !== undefined) {
202 json.svg = data['image/svg+xml'];
202 json.svg = data['image/svg+xml'];
203 };
203 };
204 if (data['image/png'] !== undefined) {
204 if (data['image/png'] !== undefined) {
205 json.png = data['image/png'];
205 json.png = data['image/png'];
206 };
206 };
207 if (data['image/jpeg'] !== undefined) {
207 if (data['image/jpeg'] !== undefined) {
208 json.jpeg = data['image/jpeg'];
208 json.jpeg = data['image/jpeg'];
209 };
209 };
210 if (data['text/latex'] !== undefined) {
210 if (data['text/latex'] !== undefined) {
211 json.latex = data['text/latex'];
211 json.latex = data['text/latex'];
212 };
212 };
213 if (data['application/json'] !== undefined) {
213 if (data['application/json'] !== undefined) {
214 json.json = data['application/json'];
214 json.json = data['application/json'];
215 };
215 };
216 if (data['application/javascript'] !== undefined) {
216 if (data['application/javascript'] !== undefined) {
217 json.javascript = data['application/javascript'];
217 json.javascript = data['application/javascript'];
218 }
218 }
219 return json;
219 return json;
220 };
220 };
221
221
222
222
223 OutputArea.prototype.append_output = function (json, dynamic) {
223 OutputArea.prototype.append_output = function (json, dynamic) {
224 // If dynamic is true, javascript output will be eval'd.
224 // If dynamic is true, javascript output will be eval'd.
225 this.expand();
225 this.expand();
226 this.flush_clear_timeout();
226 this.flush_clear_timeout();
227 if (json.output_type === 'pyout') {
227 if (json.output_type === 'pyout') {
228 this.append_pyout(json, dynamic);
228 this.append_pyout(json, dynamic);
229 } else if (json.output_type === 'pyerr') {
229 } else if (json.output_type === 'pyerr') {
230 this.append_pyerr(json);
230 this.append_pyerr(json);
231 } else if (json.output_type === 'display_data') {
231 } else if (json.output_type === 'display_data') {
232 this.append_display_data(json, dynamic);
232 this.append_display_data(json, dynamic);
233 } else if (json.output_type === 'stream') {
233 } else if (json.output_type === 'stream') {
234 this.append_stream(json);
234 this.append_stream(json);
235 };
235 };
236 this.outputs.push(json);
236 this.outputs.push(json);
237 var that = this;
237 var that = this;
238 setTimeout(function(){that.element.trigger('resize');}, 100);
238 setTimeout(function(){that.element.trigger('resize');}, 100);
239 };
239 };
240
240
241
241
242 OutputArea.prototype.create_output_area = function () {
242 OutputArea.prototype.create_output_area = function () {
243 var oa = $("<div/>").addClass("hbox output_area");
243 var oa = $("<div/>").addClass("hbox output_area");
244 if (this.prompt_area) {
244 if (this.prompt_area) {
245 oa.append($('<div/>').addClass('prompt'));
245 oa.append($('<div/>').addClass('prompt'));
246 }
246 }
247 return oa;
247 return oa;
248 };
248 };
249
249
250
250
251 OutputArea.prototype.append_pyout = function (json, dynamic) {
251 OutputArea.prototype.append_pyout = function (json, dynamic) {
252 var n = json.prompt_number || ' ';
252 var n = json.prompt_number || ' ';
253 var toinsert = this.create_output_area();
253 var toinsert = this.create_output_area();
254 if (this.prompt_area) {
254 if (this.prompt_area) {
255 toinsert.find('div.prompt').addClass('output_prompt').html('Out[' + n + ']:');
255 toinsert.find('div.prompt').addClass('output_prompt').html('Out[' + n + ']:');
256 }
256 }
257 this.append_mime_type(json, toinsert, dynamic);
257 this.append_mime_type(json, toinsert, dynamic);
258 this.element.append(toinsert);
258 this.element.append(toinsert);
259 // If we just output latex, typeset it.
259 // If we just output latex, typeset it.
260 if ((json.latex !== undefined) || (json.html !== undefined)) {
260 if ((json.latex !== undefined) || (json.html !== undefined)) {
261 this.typeset();
261 this.typeset();
262 };
262 };
263 };
263 };
264
264
265
265
266 OutputArea.prototype.append_pyerr = function (json) {
266 OutputArea.prototype.append_pyerr = function (json) {
267 var tb = json.traceback;
267 var tb = json.traceback;
268 if (tb !== undefined && tb.length > 0) {
268 if (tb !== undefined && tb.length > 0) {
269 var s = '';
269 var s = '';
270 var len = tb.length;
270 var len = tb.length;
271 for (var i=0; i<len; i++) {
271 for (var i=0; i<len; i++) {
272 s = s + tb[i] + '\n';
272 s = s + tb[i] + '\n';
273 }
273 }
274 s = s + '\n';
274 s = s + '\n';
275 var toinsert = this.create_output_area();
275 var toinsert = this.create_output_area();
276 this.append_text(s, toinsert);
276 this.append_text(s, toinsert);
277 this.element.append(toinsert);
277 this.element.append(toinsert);
278 };
278 };
279 };
279 };
280
280
281
281
282 OutputArea.prototype.append_stream = function (json) {
282 OutputArea.prototype.append_stream = function (json) {
283 // temporary fix: if stream undefined (json file written prior to this patch),
283 // temporary fix: if stream undefined (json file written prior to this patch),
284 // default to most likely stdout:
284 // default to most likely stdout:
285 if (json.stream == undefined){
285 if (json.stream == undefined){
286 json.stream = 'stdout';
286 json.stream = 'stdout';
287 }
287 }
288 var text = json.text;
288 var text = json.text;
289 var subclass = "output_"+json.stream;
289 var subclass = "output_"+json.stream;
290 if (this.outputs.length > 0){
290 if (this.outputs.length > 0){
291 // have at least one output to consider
291 // have at least one output to consider
292 var last = this.outputs[this.outputs.length-1];
292 var last = this.outputs[this.outputs.length-1];
293 if (last.output_type == 'stream' && json.stream == last.stream){
293 if (last.output_type == 'stream' && json.stream == last.stream){
294 // latest output was in the same stream,
294 // latest output was in the same stream,
295 // so append directly into its pre tag
295 // so append directly into its pre tag
296 // escape ANSI & HTML specials:
296 // escape ANSI & HTML specials:
297 var pre = this.element.find('div.'+subclass).last().find('pre');
297 var pre = this.element.find('div.'+subclass).last().find('pre');
298 var html = utils.fixCarriageReturn(
298 var html = utils.fixCarriageReturn(
299 pre.html() + utils.fixConsole(text));
299 pre.html() + utils.fixConsole(text));
300 pre.html(html);
300 pre.html(html);
301 return;
301 return;
302 }
302 }
303 }
303 }
304
304
305 if (!text.replace("\r", "")) {
305 if (!text.replace("\r", "")) {
306 // text is nothing (empty string, \r, etc.)
306 // text is nothing (empty string, \r, etc.)
307 // so don't append any elements, which might add undesirable space
307 // so don't append any elements, which might add undesirable space
308 return;
308 return;
309 }
309 }
310
310
311 // If we got here, attach a new div
311 // If we got here, attach a new div
312 var toinsert = this.create_output_area();
312 var toinsert = this.create_output_area();
313 this.append_text(text, toinsert, "output_stream "+subclass);
313 this.append_text(text, toinsert, "output_stream "+subclass);
314 this.element.append(toinsert);
314 this.element.append(toinsert);
315 };
315 };
316
316
317
317
318 OutputArea.prototype.append_display_data = function (json, dynamic) {
318 OutputArea.prototype.append_display_data = function (json, dynamic) {
319 var toinsert = this.create_output_area();
319 var toinsert = this.create_output_area();
320 this.append_mime_type(json, toinsert, dynamic);
320 this.append_mime_type(json, toinsert, dynamic);
321 this.element.append(toinsert);
321 this.element.append(toinsert);
322 // If we just output latex, typeset it.
322 // If we just output latex, typeset it.
323 if ( (json.latex !== undefined) || (json.html !== undefined) ) {
323 if ( (json.latex !== undefined) || (json.html !== undefined) ) {
324 this.typeset();
324 this.typeset();
325 };
325 };
326 };
326 };
327
327
328 OutputArea.display_order = ['javascript','html','latex','svg','png','jpeg','text'];
328
329
329 OutputArea.prototype.append_mime_type = function (json, element, dynamic) {
330 OutputArea.prototype.append_mime_type = function (json, element, dynamic) {
330 if (json.javascript !== undefined && dynamic) {
331 for(var type_i in OutputArea.display_order){
331 this.append_javascript(json.javascript, element, dynamic);
332 var type = OutputArea.display_order[type_i];
332 } else if (json.html !== undefined) {
333 if(json[type] != undefined ){
333 this.append_html(json.html, element);
334 if(type != 'javascript' && dynamic){
334 } else if (json.latex !== undefined) {
335 this['append_'+type](json[type],element)
335 this.append_latex(json.latex, element);
336 } else {
336 } else if (json.svg !== undefined) {
337 this.append_javascript(json.javascript, element, dynamic);
337 this.append_svg(json.svg, element);
338 }
338 } else if (json.png !== undefined) {
339 return
339 this.append_png(json.png, element);
340 }
340 } else if (json.jpeg !== undefined) {
341 }
341 this.append_jpeg(json.jpeg, element);
342 } else if (json.text !== undefined) {
343 this.append_text(json.text, element);
344 };
345 };
342 };
346
343
347
344
348 OutputArea.prototype.append_html = function (html, element) {
345 OutputArea.prototype.append_html = function (html, element) {
349 var toinsert = $("<div/>").addClass("box-flex1 output_subarea output_html rendered_html");
346 var toinsert = $("<div/>").addClass("box-flex1 output_subarea output_html rendered_html");
350 toinsert.append(html);
347 toinsert.append(html);
351 element.append(toinsert);
348 element.append(toinsert);
352 };
349 };
353
350
354
351
355 OutputArea.prototype.append_javascript = function (js, container) {
352 OutputArea.prototype.append_javascript = function (js, container) {
356 // We just eval the JS code, element appears in the local scope.
353 // We just eval the JS code, element appears in the local scope.
357 var element = $("<div/>").addClass("box-flex1 output_subarea");
354 var element = $("<div/>").addClass("box-flex1 output_subarea");
358 container.append(element);
355 container.append(element);
359 // Div for js shouldn't be drawn, as it will add empty height to the area.
356 // Div for js shouldn't be drawn, as it will add empty height to the area.
360 container.hide();
357 container.hide();
361 // If the Javascript appends content to `element` that should be drawn, then
358 // If the Javascript appends content to `element` that should be drawn, then
362 // it must also call `container.show()`.
359 // it must also call `container.show()`.
363 try {
360 try {
364 eval(js);
361 eval(js);
365 } catch(err) {
362 } catch(err) {
366 console.log('Error in Javascript!');
363 console.log('Error in Javascript!');
367 console.log(err);
364 console.log(err);
368 container.show();
365 container.show();
369 element.append($('<div/>')
366 element.append($('<div/>')
370 .html("Error in Javascript !<br/>"+
367 .html("Error in Javascript !<br/>"+
371 err.toString()+
368 err.toString()+
372 '<br/>See your browser Javascript console for more details.')
369 '<br/>See your browser Javascript console for more details.')
373 .addClass('js-error')
370 .addClass('js-error')
374 );
371 );
375 }
372 }
376 }
373 }
377
374
378
375
379 OutputArea.prototype.append_text = function (data, element, extra_class) {
376 OutputArea.prototype.append_text = function (data, element, extra_class) {
380 var toinsert = $("<div/>").addClass("box-flex1 output_subarea output_text");
377 var toinsert = $("<div/>").addClass("box-flex1 output_subarea output_text");
381 // escape ANSI & HTML specials in plaintext:
378 // escape ANSI & HTML specials in plaintext:
382 data = utils.wrapUrls(data);
379 data = utils.wrapUrls(data);
383 data = utils.fixConsole(data);
380 data = utils.fixConsole(data);
384 data = utils.fixCarriageReturn(data);
381 data = utils.fixCarriageReturn(data);
385 data = utils.autoLinkUrls(data);
382 data = utils.autoLinkUrls(data);
386 if (extra_class){
383 if (extra_class){
387 toinsert.addClass(extra_class);
384 toinsert.addClass(extra_class);
388 }
385 }
389 toinsert.append($("<pre/>").html(data));
386 toinsert.append($("<pre/>").html(data));
390 element.append(toinsert);
387 element.append(toinsert);
391 };
388 };
392
389
393
390
394 OutputArea.prototype.append_svg = function (svg, element) {
391 OutputArea.prototype.append_svg = function (svg, element) {
395 var toinsert = $("<div/>").addClass("box-flex1 output_subarea output_svg");
392 var toinsert = $("<div/>").addClass("box-flex1 output_subarea output_svg");
396 toinsert.append(svg);
393 toinsert.append(svg);
397 element.append(toinsert);
394 element.append(toinsert);
398 };
395 };
399
396
400
397
401 OutputArea.prototype._dblclick_to_reset_size = function (img) {
398 OutputArea.prototype._dblclick_to_reset_size = function (img) {
402 // schedule wrapping image in resizable after a delay,
399 // schedule wrapping image in resizable after a delay,
403 // so we don't end up calling resize on a zero-size object
400 // so we don't end up calling resize on a zero-size object
404 var that = this;
401 var that = this;
405 setTimeout(function () {
402 setTimeout(function () {
406 var h0 = img.height();
403 var h0 = img.height();
407 var w0 = img.width();
404 var w0 = img.width();
408 if (!(h0 && w0)) {
405 if (!(h0 && w0)) {
409 // zero size, schedule another timeout
406 // zero size, schedule another timeout
410 that._dblclick_to_reset_size(img);
407 that._dblclick_to_reset_size(img);
411 return
408 return
412 }
409 }
413 img.resizable({
410 img.resizable({
414 aspectRatio: true,
411 aspectRatio: true,
415 autoHide: true
412 autoHide: true
416 });
413 });
417 img.dblclick(function () {
414 img.dblclick(function () {
418 // resize wrapper & image together for some reason:
415 // resize wrapper & image together for some reason:
419 img.parent().height(h0);
416 img.parent().height(h0);
420 img.height(h0);
417 img.height(h0);
421 img.parent().width(w0);
418 img.parent().width(w0);
422 img.width(w0);
419 img.width(w0);
423 });
420 });
424 }, 250);
421 }, 250);
425 }
422 }
426
423
427
424
428 OutputArea.prototype.append_png = function (png, element) {
425 OutputArea.prototype.append_png = function (png, element) {
429 var toinsert = $("<div/>").addClass("box-flex1 output_subarea output_png");
426 var toinsert = $("<div/>").addClass("box-flex1 output_subarea output_png");
430 var img = $("<img/>").attr('src','data:image/png;base64,'+png);
427 var img = $("<img/>").attr('src','data:image/png;base64,'+png);
431 this._dblclick_to_reset_size(img);
428 this._dblclick_to_reset_size(img);
432 toinsert.append(img);
429 toinsert.append(img);
433 element.append(toinsert);
430 element.append(toinsert);
434 };
431 };
435
432
436
433
437 OutputArea.prototype.append_jpeg = function (jpeg, element) {
434 OutputArea.prototype.append_jpeg = function (jpeg, element) {
438 var toinsert = $("<div/>").addClass("box-flex1 output_subarea output_jpeg");
435 var toinsert = $("<div/>").addClass("box-flex1 output_subarea output_jpeg");
439 var img = $("<img/>").attr('src','data:image/jpeg;base64,'+jpeg);
436 var img = $("<img/>").attr('src','data:image/jpeg;base64,'+jpeg);
440 this._dblclick_to_reset_size(img);
437 this._dblclick_to_reset_size(img);
441 toinsert.append(img);
438 toinsert.append(img);
442 element.append(toinsert);
439 element.append(toinsert);
443 };
440 };
444
441
445
442
446 OutputArea.prototype.append_latex = function (latex, element) {
443 OutputArea.prototype.append_latex = function (latex, element) {
447 // This method cannot do the typesetting because the latex first has to
444 // This method cannot do the typesetting because the latex first has to
448 // be on the page.
445 // be on the page.
449 var toinsert = $("<div/>").addClass("box-flex1 output_subarea output_latex");
446 var toinsert = $("<div/>").addClass("box-flex1 output_subarea output_latex");
450 toinsert.append(latex);
447 toinsert.append(latex);
451 element.append(toinsert);
448 element.append(toinsert);
452 };
449 };
453
450
454
451
455 OutputArea.prototype.handle_clear_output = function (content) {
452 OutputArea.prototype.handle_clear_output = function (content) {
456 this.clear_output(content.stdout, content.stderr, content.other);
453 this.clear_output(content.stdout, content.stderr, content.other);
457 }
454 }
458
455
459
456
460 OutputArea.prototype.clear_output = function (stdout, stderr, other) {
457 OutputArea.prototype.clear_output = function (stdout, stderr, other) {
461 var that = this;
458 var that = this;
462 if (this.clear_out_timeout != null){
459 if (this.clear_out_timeout != null){
463 // fire previous pending clear *immediately*
460 // fire previous pending clear *immediately*
464 clearTimeout(this.clear_out_timeout);
461 clearTimeout(this.clear_out_timeout);
465 this.clear_out_timeout = null;
462 this.clear_out_timeout = null;
466 this.clear_output_callback(this._clear_stdout, this._clear_stderr, this._clear_other);
463 this.clear_output_callback(this._clear_stdout, this._clear_stderr, this._clear_other);
467 }
464 }
468 // store flags for flushing the timeout
465 // store flags for flushing the timeout
469 this._clear_stdout = stdout;
466 this._clear_stdout = stdout;
470 this._clear_stderr = stderr;
467 this._clear_stderr = stderr;
471 this._clear_other = other;
468 this._clear_other = other;
472 this.clear_out_timeout = setTimeout(function() {
469 this.clear_out_timeout = setTimeout(function() {
473 // really clear timeout only after a short delay
470 // really clear timeout only after a short delay
474 // this reduces flicker in 'clear_output; print' cases
471 // this reduces flicker in 'clear_output; print' cases
475 that.clear_out_timeout = null;
472 that.clear_out_timeout = null;
476 that._clear_stdout = that._clear_stderr = that._clear_other = null;
473 that._clear_stdout = that._clear_stderr = that._clear_other = null;
477 that.clear_output_callback(stdout, stderr, other);
474 that.clear_output_callback(stdout, stderr, other);
478 }, 500
475 }, 500
479 );
476 );
480 };
477 };
481
478
482
479
483 OutputArea.prototype.clear_output_callback = function (stdout, stderr, other) {
480 OutputArea.prototype.clear_output_callback = function (stdout, stderr, other) {
484 var output_div = this.element;
481 var output_div = this.element;
485
482
486 if (stdout && stderr && other){
483 if (stdout && stderr && other){
487 // clear all, no need for logic
484 // clear all, no need for logic
488 output_div.html("");
485 output_div.html("");
489 this.outputs = [];
486 this.outputs = [];
490 this.unscroll_area();
487 this.unscroll_area();
491 return;
488 return;
492 }
489 }
493 // remove html output
490 // remove html output
494 // each output_subarea that has an identifying class is in an output_area
491 // each output_subarea that has an identifying class is in an output_area
495 // which is the element to be removed.
492 // which is the element to be removed.
496 if (stdout) {
493 if (stdout) {
497 output_div.find("div.output_stdout").parent().remove();
494 output_div.find("div.output_stdout").parent().remove();
498 }
495 }
499 if (stderr) {
496 if (stderr) {
500 output_div.find("div.output_stderr").parent().remove();
497 output_div.find("div.output_stderr").parent().remove();
501 }
498 }
502 if (other) {
499 if (other) {
503 output_div.find("div.output_subarea").not("div.output_stderr").not("div.output_stdout").parent().remove();
500 output_div.find("div.output_subarea").not("div.output_stderr").not("div.output_stdout").parent().remove();
504 }
501 }
505 this.unscroll_area();
502 this.unscroll_area();
506
503
507 // remove cleared outputs from JSON list:
504 // remove cleared outputs from JSON list:
508 for (var i = this.outputs.length - 1; i >= 0; i--) {
505 for (var i = this.outputs.length - 1; i >= 0; i--) {
509 var out = this.outputs[i];
506 var out = this.outputs[i];
510 var output_type = out.output_type;
507 var output_type = out.output_type;
511 if (output_type == "display_data" && other) {
508 if (output_type == "display_data" && other) {
512 this.outputs.splice(i,1);
509 this.outputs.splice(i,1);
513 } else if (output_type == "stream") {
510 } else if (output_type == "stream") {
514 if (stdout && out.stream == "stdout") {
511 if (stdout && out.stream == "stdout") {
515 this.outputs.splice(i,1);
512 this.outputs.splice(i,1);
516 } else if (stderr && out.stream == "stderr") {
513 } else if (stderr && out.stream == "stderr") {
517 this.outputs.splice(i,1);
514 this.outputs.splice(i,1);
518 }
515 }
519 }
516 }
520 }
517 }
521 };
518 };
522
519
523
520
524 OutputArea.prototype.flush_clear_timeout = function() {
521 OutputArea.prototype.flush_clear_timeout = function() {
525 var output_div = this.element;
522 var output_div = this.element;
526 if (this.clear_out_timeout){
523 if (this.clear_out_timeout){
527 clearTimeout(this.clear_out_timeout);
524 clearTimeout(this.clear_out_timeout);
528 this.clear_out_timeout = null;
525 this.clear_out_timeout = null;
529 this.clear_output_callback(this._clear_stdout, this._clear_stderr, this._clear_other);
526 this.clear_output_callback(this._clear_stdout, this._clear_stderr, this._clear_other);
530 };
527 };
531 }
528 }
532
529
533
530
534 // JSON serialization
531 // JSON serialization
535
532
536 OutputArea.prototype.fromJSON = function (outputs) {
533 OutputArea.prototype.fromJSON = function (outputs) {
537 var len = outputs.length;
534 var len = outputs.length;
538 for (var i=0; i<len; i++) {
535 for (var i=0; i<len; i++) {
539 // append with dynamic=false.
536 // append with dynamic=false.
540 this.append_output(outputs[i], false);
537 this.append_output(outputs[i], false);
541 };
538 };
542 };
539 };
543
540
544
541
545 OutputArea.prototype.toJSON = function () {
542 OutputArea.prototype.toJSON = function () {
546 var outputs = [];
543 var outputs = [];
547 var len = this.outputs.length;
544 var len = this.outputs.length;
548 for (var i=0; i<len; i++) {
545 for (var i=0; i<len; i++) {
549 outputs[i] = this.outputs[i];
546 outputs[i] = this.outputs[i];
550 };
547 };
551 return outputs;
548 return outputs;
552 };
549 };
553
550
554
551
555 IPython.OutputArea = OutputArea;
552 IPython.OutputArea = OutputArea;
556
553
557 return IPython;
554 return IPython;
558
555
559 }(IPython));
556 }(IPython));
General Comments 0
You need to be logged in to leave comments. Login now