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