Show More
@@ -0,0 +1,402 b'' | |||||
|
1 | //---------------------------------------------------------------------------- | |||
|
2 | // Copyright (C) 2008-2011 The IPython Development Team | |||
|
3 | // | |||
|
4 | // Distributed under the terms of the BSD License. The full license is in | |||
|
5 | // the file COPYING, distributed as part of this software. | |||
|
6 | //---------------------------------------------------------------------------- | |||
|
7 | ||||
|
8 | //============================================================================ | |||
|
9 | // OutputArea | |||
|
10 | //============================================================================ | |||
|
11 | ||||
|
12 | var IPython = (function (IPython) { | |||
|
13 | "use strict"; | |||
|
14 | ||||
|
15 | var utils = IPython.utils; | |||
|
16 | ||||
|
17 | var OutputArea = function (selector, prompt_area) { | |||
|
18 | this.selector = selector; | |||
|
19 | this.element = $(selector); | |||
|
20 | this.outputs = []; | |||
|
21 | this.collapsed = false; | |||
|
22 | this.clear_out_timeout = null; | |||
|
23 | if (prompt_area === undefined) { | |||
|
24 | this.prompt_area = true; | |||
|
25 | } | |||
|
26 | this.style(); | |||
|
27 | }; | |||
|
28 | ||||
|
29 | ||||
|
30 | OutputArea.prototype.style = function () { | |||
|
31 | this.element.addClass('output vbox'); | |||
|
32 | this.collapse(); | |||
|
33 | }; | |||
|
34 | ||||
|
35 | ||||
|
36 | OutputArea.prototype.collapse = function () { | |||
|
37 | if (!this.collapsed) { | |||
|
38 | this.element.hide(); | |||
|
39 | this.collapsed = true; | |||
|
40 | }; | |||
|
41 | }; | |||
|
42 | ||||
|
43 | ||||
|
44 | OutputArea.prototype.expand = function () { | |||
|
45 | if (this.collapsed) { | |||
|
46 | this.element.show(); | |||
|
47 | this.collapsed = false; | |||
|
48 | }; | |||
|
49 | }; | |||
|
50 | ||||
|
51 | ||||
|
52 | OutputArea.prototype.toggle_output = function () { | |||
|
53 | if (this.collapsed) { | |||
|
54 | this.expand(); | |||
|
55 | } else { | |||
|
56 | this.collapse(); | |||
|
57 | }; | |||
|
58 | }; | |||
|
59 | ||||
|
60 | ||||
|
61 | // typeset with MathJax if MathJax is available | |||
|
62 | OutputArea.prototype.typeset = function () { | |||
|
63 | if (window.MathJax){ | |||
|
64 | MathJax.Hub.Queue(["Typeset",MathJax.Hub]); | |||
|
65 | } | |||
|
66 | }; | |||
|
67 | ||||
|
68 | ||||
|
69 | OutputArea.prototype.handle_output = function (msg_type, content) { | |||
|
70 | var json = {}; | |||
|
71 | json.output_type = msg_type; | |||
|
72 | if (msg_type === "stream") { | |||
|
73 | json.text = content.data; | |||
|
74 | json.stream = content.name; | |||
|
75 | } else if (msg_type === "display_data") { | |||
|
76 | json = this.convert_mime_types(json, content.data); | |||
|
77 | } else if (msg_type === "pyout") { | |||
|
78 | json.prompt_number = content.execution_count; | |||
|
79 | json = this.convert_mime_types(json, content.data); | |||
|
80 | } else if (msg_type === "pyerr") { | |||
|
81 | json.ename = content.ename; | |||
|
82 | json.evalue = content.evalue; | |||
|
83 | json.traceback = content.traceback; | |||
|
84 | }; | |||
|
85 | // append with dynamic=true | |||
|
86 | this.append_output(json, true); | |||
|
87 | }; | |||
|
88 | ||||
|
89 | ||||
|
90 | OutputArea.prototype.convert_mime_types = function (json, data) { | |||
|
91 | if (data['text/plain'] !== undefined) { | |||
|
92 | json.text = data['text/plain']; | |||
|
93 | }; | |||
|
94 | if (data['text/html'] !== undefined) { | |||
|
95 | json.html = data['text/html']; | |||
|
96 | }; | |||
|
97 | if (data['image/svg+xml'] !== undefined) { | |||
|
98 | json.svg = data['image/svg+xml']; | |||
|
99 | }; | |||
|
100 | if (data['image/png'] !== undefined) { | |||
|
101 | json.png = data['image/png']; | |||
|
102 | }; | |||
|
103 | if (data['image/jpeg'] !== undefined) { | |||
|
104 | json.jpeg = data['image/jpeg']; | |||
|
105 | }; | |||
|
106 | if (data['text/latex'] !== undefined) { | |||
|
107 | json.latex = data['text/latex']; | |||
|
108 | }; | |||
|
109 | if (data['application/json'] !== undefined) { | |||
|
110 | json.json = data['application/json']; | |||
|
111 | }; | |||
|
112 | if (data['application/javascript'] !== undefined) { | |||
|
113 | json.javascript = data['application/javascript']; | |||
|
114 | } | |||
|
115 | return json; | |||
|
116 | }; | |||
|
117 | ||||
|
118 | ||||
|
119 | OutputArea.prototype.append_output = function (json, dynamic) { | |||
|
120 | // If dynamic is true, javascript output will be eval'd. | |||
|
121 | this.expand(); | |||
|
122 | this.flush_clear_timeout(); | |||
|
123 | if (json.output_type === 'pyout') { | |||
|
124 | this.append_pyout(json, dynamic); | |||
|
125 | } else if (json.output_type === 'pyerr') { | |||
|
126 | this.append_pyerr(json); | |||
|
127 | } else if (json.output_type === 'display_data') { | |||
|
128 | this.append_display_data(json, dynamic); | |||
|
129 | } else if (json.output_type === 'stream') { | |||
|
130 | this.append_stream(json); | |||
|
131 | }; | |||
|
132 | this.outputs.push(json); | |||
|
133 | }; | |||
|
134 | ||||
|
135 | ||||
|
136 | OutputArea.prototype.create_output_area = function () { | |||
|
137 | var oa = $("<div/>").addClass("hbox output_area"); | |||
|
138 | if (this.prompt_area) { | |||
|
139 | oa.append($('<div/>').addClass('prompt')); | |||
|
140 | } | |||
|
141 | return oa; | |||
|
142 | }; | |||
|
143 | ||||
|
144 | ||||
|
145 | OutputArea.prototype.append_pyout = function (json, dynamic) { | |||
|
146 | var n = json.prompt_number || ' '; | |||
|
147 | var toinsert = this.create_output_area(); | |||
|
148 | if (this.prompt_area) { | |||
|
149 | toinsert.find('div.prompt').addClass('output_prompt').html('Out[' + n + ']:'); | |||
|
150 | } | |||
|
151 | this.append_mime_type(json, toinsert, dynamic); | |||
|
152 | this.element.append(toinsert); | |||
|
153 | // If we just output latex, typeset it. | |||
|
154 | if ((json.latex !== undefined) || (json.html !== undefined)) { | |||
|
155 | this.typeset(); | |||
|
156 | }; | |||
|
157 | }; | |||
|
158 | ||||
|
159 | ||||
|
160 | OutputArea.prototype.append_pyerr = function (json) { | |||
|
161 | var tb = json.traceback; | |||
|
162 | if (tb !== undefined && tb.length > 0) { | |||
|
163 | var s = ''; | |||
|
164 | var len = tb.length; | |||
|
165 | for (var i=0; i<len; i++) { | |||
|
166 | s = s + tb[i] + '\n'; | |||
|
167 | } | |||
|
168 | s = s + '\n'; | |||
|
169 | var toinsert = this.create_output_area(); | |||
|
170 | this.append_text(s, toinsert); | |||
|
171 | this.element.append(toinsert); | |||
|
172 | }; | |||
|
173 | }; | |||
|
174 | ||||
|
175 | ||||
|
176 | OutputArea.prototype.append_stream = function (json) { | |||
|
177 | // temporary fix: if stream undefined (json file written prior to this patch), | |||
|
178 | // default to most likely stdout: | |||
|
179 | if (json.stream == undefined){ | |||
|
180 | json.stream = 'stdout'; | |||
|
181 | } | |||
|
182 | if (!utils.fixConsole(json.text)){ | |||
|
183 | // fixConsole gives nothing (empty string, \r, etc.) | |||
|
184 | // so don't append any elements, which might add undesirable space | |||
|
185 | return; | |||
|
186 | } | |||
|
187 | var subclass = "output_"+json.stream; | |||
|
188 | if (this.outputs.length > 0){ | |||
|
189 | // have at least one output to consider | |||
|
190 | var last = this.outputs[this.outputs.length-1]; | |||
|
191 | if (last.output_type == 'stream' && json.stream == last.stream){ | |||
|
192 | // latest output was in the same stream, | |||
|
193 | // so append directly into its pre tag | |||
|
194 | // escape ANSI & HTML specials: | |||
|
195 | var text = utils.fixConsole(json.text); | |||
|
196 | this.element.find('div.'+subclass).last().find('pre').append(text); | |||
|
197 | return; | |||
|
198 | } | |||
|
199 | } | |||
|
200 | ||||
|
201 | // If we got here, attach a new div | |||
|
202 | var toinsert = this.create_output_area(); | |||
|
203 | this.append_text(json.text, toinsert, "output_stream "+subclass); | |||
|
204 | this.element.append(toinsert); | |||
|
205 | }; | |||
|
206 | ||||
|
207 | ||||
|
208 | OutputArea.prototype.append_display_data = function (json, dynamic) { | |||
|
209 | var toinsert = this.create_output_area(); | |||
|
210 | this.append_mime_type(json, toinsert, dynamic); | |||
|
211 | this.element.append(toinsert); | |||
|
212 | // If we just output latex, typeset it. | |||
|
213 | if ( (json.latex !== undefined) || (json.html !== undefined) ) { | |||
|
214 | this.typeset(); | |||
|
215 | }; | |||
|
216 | }; | |||
|
217 | ||||
|
218 | ||||
|
219 | OutputArea.prototype.append_mime_type = function (json, element, dynamic) { | |||
|
220 | if (json.javascript !== undefined && dynamic) { | |||
|
221 | this.append_javascript(json.javascript, element, dynamic); | |||
|
222 | } else if (json.html !== undefined) { | |||
|
223 | this.append_html(json.html, element); | |||
|
224 | } else if (json.latex !== undefined) { | |||
|
225 | this.append_latex(json.latex, element); | |||
|
226 | } else if (json.svg !== undefined) { | |||
|
227 | this.append_svg(json.svg, element); | |||
|
228 | } else if (json.png !== undefined) { | |||
|
229 | this.append_png(json.png, element); | |||
|
230 | } else if (json.jpeg !== undefined) { | |||
|
231 | this.append_jpeg(json.jpeg, element); | |||
|
232 | } else if (json.text !== undefined) { | |||
|
233 | this.append_text(json.text, element); | |||
|
234 | }; | |||
|
235 | }; | |||
|
236 | ||||
|
237 | ||||
|
238 | OutputArea.prototype.append_html = function (html, element) { | |||
|
239 | var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_html rendered_html"); | |||
|
240 | toinsert.append(html); | |||
|
241 | element.append(toinsert); | |||
|
242 | }; | |||
|
243 | ||||
|
244 | ||||
|
245 | OutputArea.prototype.append_javascript = function (js, container) { | |||
|
246 | // We just eval the JS code, element appears in the local scope. | |||
|
247 | var element = $("<div/>").addClass("box_flex1 output_subarea"); | |||
|
248 | var kernel = this.kernel; | |||
|
249 | container.append(element); | |||
|
250 | // Div for js shouldn't be drawn, as it will add empty height to the area. | |||
|
251 | container.hide(); | |||
|
252 | // If the Javascript appends content to `element` that should be drawn, then | |||
|
253 | // it must also call `container.show()`. | |||
|
254 | eval(js); | |||
|
255 | } | |||
|
256 | ||||
|
257 | ||||
|
258 | OutputArea.prototype.append_text = function (data, element, extra_class) { | |||
|
259 | var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_text"); | |||
|
260 | // escape ANSI & HTML specials in plaintext: | |||
|
261 | data = utils.fixConsole(data); | |||
|
262 | if (extra_class){ | |||
|
263 | toinsert.addClass(extra_class); | |||
|
264 | } | |||
|
265 | toinsert.append($("<pre/>").html(data)); | |||
|
266 | element.append(toinsert); | |||
|
267 | }; | |||
|
268 | ||||
|
269 | ||||
|
270 | OutputArea.prototype.append_svg = function (svg, element) { | |||
|
271 | var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_svg"); | |||
|
272 | toinsert.append(svg); | |||
|
273 | element.append(toinsert); | |||
|
274 | }; | |||
|
275 | ||||
|
276 | ||||
|
277 | OutputArea.prototype.append_png = function (png, element) { | |||
|
278 | var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_png"); | |||
|
279 | toinsert.append($("<img/>").attr('src','data:image/png;base64,'+png)); | |||
|
280 | element.append(toinsert); | |||
|
281 | }; | |||
|
282 | ||||
|
283 | ||||
|
284 | OutputArea.prototype.append_jpeg = function (jpeg, element) { | |||
|
285 | var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_jpeg"); | |||
|
286 | toinsert.append($("<img/>").attr('src','data:image/jpeg;base64,'+jpeg)); | |||
|
287 | element.append(toinsert); | |||
|
288 | }; | |||
|
289 | ||||
|
290 | ||||
|
291 | OutputArea.prototype.append_latex = function (latex, element) { | |||
|
292 | // This method cannot do the typesetting because the latex first has to | |||
|
293 | // be on the page. | |||
|
294 | var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_latex"); | |||
|
295 | toinsert.append(latex); | |||
|
296 | element.append(toinsert); | |||
|
297 | }; | |||
|
298 | ||||
|
299 | ||||
|
300 | OutputArea.prototype.handle_clear_output = function (content) { | |||
|
301 | this.clear_output(content.stdout, content.stderr, content.other); | |||
|
302 | } | |||
|
303 | ||||
|
304 | ||||
|
305 | OutputArea.prototype.clear_output = function (stdout, stderr, other) { | |||
|
306 | var that = this; | |||
|
307 | if (this.clear_out_timeout != null){ | |||
|
308 | // fire previous pending clear *immediately* | |||
|
309 | clearTimeout(this.clear_out_timeout); | |||
|
310 | this.clear_out_timeout = null; | |||
|
311 | this.clear_output_callback(this._clear_stdout, this._clear_stderr, this._clear_other); | |||
|
312 | } | |||
|
313 | // store flags for flushing the timeout | |||
|
314 | this._clear_stdout = stdout; | |||
|
315 | this._clear_stderr = stderr; | |||
|
316 | this._clear_other = other; | |||
|
317 | this.clear_out_timeout = setTimeout(function() { | |||
|
318 | // really clear timeout only after a short delay | |||
|
319 | // this reduces flicker in 'clear_output; print' cases | |||
|
320 | that.clear_out_timeout = null; | |||
|
321 | that._clear_stdout = that._clear_stderr = that._clear_other = null; | |||
|
322 | that.clear_output_callback(stdout, stderr, other); | |||
|
323 | }, 500 | |||
|
324 | ); | |||
|
325 | }; | |||
|
326 | ||||
|
327 | ||||
|
328 | OutputArea.prototype.clear_output_callback = function (stdout, stderr, other) { | |||
|
329 | var output_div = this.element; | |||
|
330 | ||||
|
331 | if (stdout && stderr && other){ | |||
|
332 | // clear all, no need for logic | |||
|
333 | output_div.html(""); | |||
|
334 | this.outputs = []; | |||
|
335 | return; | |||
|
336 | } | |||
|
337 | // remove html output | |||
|
338 | // each output_subarea that has an identifying class is in an output_area | |||
|
339 | // which is the element to be removed. | |||
|
340 | if (stdout) { | |||
|
341 | output_div.find("div.output_stdout").parent().remove(); | |||
|
342 | } | |||
|
343 | if (stderr) { | |||
|
344 | output_div.find("div.output_stderr").parent().remove(); | |||
|
345 | } | |||
|
346 | if (other) { | |||
|
347 | output_div.find("div.output_subarea").not("div.output_stderr").not("div.output_stdout").parent().remove(); | |||
|
348 | } | |||
|
349 | ||||
|
350 | // remove cleared outputs from JSON list: | |||
|
351 | for (var i = this.outputs.length - 1; i >= 0; i--) { | |||
|
352 | var out = this.outputs[i]; | |||
|
353 | var output_type = out.output_type; | |||
|
354 | if (output_type == "display_data" && other) { | |||
|
355 | this.outputs.splice(i,1); | |||
|
356 | } else if (output_type == "stream") { | |||
|
357 | if (stdout && out.stream == "stdout") { | |||
|
358 | this.outputs.splice(i,1); | |||
|
359 | } else if (stderr && out.stream == "stderr") { | |||
|
360 | this.outputs.splice(i,1); | |||
|
361 | } | |||
|
362 | } | |||
|
363 | } | |||
|
364 | }; | |||
|
365 | ||||
|
366 | ||||
|
367 | OutputArea.prototype.flush_clear_timeout = function() { | |||
|
368 | var output_div = this.element; | |||
|
369 | if (this.clear_out_timeout){ | |||
|
370 | clearTimeout(this.clear_out_timeout); | |||
|
371 | this.clear_out_timeout = null; | |||
|
372 | this.clear_output_callback(this._clear_stdout, this._clear_stderr, this._clear_other); | |||
|
373 | }; | |||
|
374 | } | |||
|
375 | ||||
|
376 | ||||
|
377 | // JSON serialization | |||
|
378 | ||||
|
379 | OutputArea.prototype.fromJSON = function (outputs) { | |||
|
380 | var len = outputs.length; | |||
|
381 | for (var i=0; i<len; i++) { | |||
|
382 | // append with dynamic=false. | |||
|
383 | this.append_output(outputs[i], false); | |||
|
384 | }; | |||
|
385 | }; | |||
|
386 | ||||
|
387 | ||||
|
388 | OutputArea.prototype.toJSON = function () { | |||
|
389 | var outputs = []; | |||
|
390 | var len = this.outputs.length; | |||
|
391 | for (var i=0; i<len; i++) { | |||
|
392 | outputs[i] = this.outputs[i]; | |||
|
393 | }; | |||
|
394 | return outputs; | |||
|
395 | }; | |||
|
396 | ||||
|
397 | ||||
|
398 | IPython.OutputArea = OutputArea; | |||
|
399 | ||||
|
400 | return IPython; | |||
|
401 | ||||
|
402 | }(IPython)); |
@@ -19,9 +19,6 b' var IPython = (function (IPython) {' | |||||
19 | this.kernel = kernel; |
|
19 | this.kernel = kernel; | |
20 | this.code_mirror = null; |
|
20 | this.code_mirror = null; | |
21 | this.input_prompt_number = null; |
|
21 | this.input_prompt_number = null; | |
22 | this.outputs = []; |
|
|||
23 | this.collapsed = false; |
|
|||
24 | this.clear_out_timeout = null; |
|
|||
25 | this.tooltip_on_tab = true; |
|
22 | this.tooltip_on_tab = true; | |
26 | IPython.Cell.apply(this, arguments); |
|
23 | IPython.Cell.apply(this, arguments); | |
27 | }; |
|
24 | }; | |
@@ -44,10 +41,10 b' var IPython = (function (IPython) {' | |||||
44 | onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this) |
|
41 | onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this) | |
45 | }); |
|
42 | }); | |
46 | input.append(input_area); |
|
43 | input.append(input_area); | |
47 |
var output = $('<div></div>') |
|
44 | var output = $('<div></div>'); | |
48 | cell.append(input).append(output); |
|
45 | cell.append(input).append(output); | |
49 | this.element = cell; |
|
46 | this.element = cell; | |
50 | this.collapse(); |
|
47 | this.output_area = new IPython.OutputArea(output, false); | |
51 |
|
48 | |||
52 | // construct a completer only if class exist |
|
49 | // construct a completer only if class exist | |
53 | // otherwise no print view |
|
50 | // otherwise no print view | |
@@ -146,14 +143,14 b' var IPython = (function (IPython) {' | |||||
146 | // Kernel related calls. |
|
143 | // Kernel related calls. | |
147 |
|
144 | |||
148 | CodeCell.prototype.execute = function () { |
|
145 | CodeCell.prototype.execute = function () { | |
149 | this.clear_output(true, true, true); |
|
146 | this.output_area.clear_output(true, true, true); | |
150 | this.set_input_prompt('*'); |
|
147 | this.set_input_prompt('*'); | |
151 | this.element.addClass("running"); |
|
148 | this.element.addClass("running"); | |
152 | var code = this.get_text(); |
|
149 | var code = this.get_text(); | |
153 | var callbacks = { |
|
150 | var callbacks = { | |
154 | 'execute_reply': $.proxy(this._handle_execute_reply, this), |
|
151 | 'execute_reply': $.proxy(this._handle_execute_reply, this), | |
155 | 'output': $.proxy(this._handle_output, this), |
|
152 | 'output': $.proxy(this.output_area.handle_output, this.output_area), | |
156 | 'clear_output': $.proxy(this._handle_clear_output, this), |
|
153 | 'clear_output': $.proxy(this.output_area.handle_clear_output, this.output_area), | |
157 | 'cell': this |
|
154 | 'cell': this | |
158 | }; |
|
155 | }; | |
159 | var msg_id = this.kernel.execute(this.get_text(), callbacks, {silent: false}); |
|
156 | var msg_id = this.kernel.execute(this.get_text(), callbacks, {silent: false}); | |
@@ -188,27 +185,17 b' var IPython = (function (IPython) {' | |||||
188 |
|
185 | |||
189 |
|
186 | |||
190 | CodeCell.prototype.collapse = function () { |
|
187 | CodeCell.prototype.collapse = function () { | |
191 | if (!this.collapsed) { |
|
188 | this.output_area.collapse(); | |
192 | this.element.find('div.output').hide(); |
|
|||
193 | this.collapsed = true; |
|
|||
194 | }; |
|
|||
195 | }; |
|
189 | }; | |
196 |
|
190 | |||
197 |
|
191 | |||
198 | CodeCell.prototype.expand = function () { |
|
192 | CodeCell.prototype.expand = function () { | |
199 | if (this.collapsed) { |
|
193 | this.output_area.expand(); | |
200 | this.element.find('div.output').show(); |
|
|||
201 | this.collapsed = false; |
|
|||
202 | }; |
|
|||
203 | }; |
|
194 | }; | |
204 |
|
195 | |||
205 |
|
196 | |||
206 | CodeCell.prototype.toggle_output = function () { |
|
197 | CodeCell.prototype.toggle_output = function () { | |
207 | if (this.collapsed) { |
|
198 | this.output_area.toggle_output(); | |
208 | this.expand(); |
|
|||
209 | } else { |
|
|||
210 | this.collapse(); |
|
|||
211 | }; |
|
|||
212 | }; |
|
199 | }; | |
213 |
|
200 | |||
214 |
|
201 | |||
@@ -254,312 +241,11 b' var IPython = (function (IPython) {' | |||||
254 | }; |
|
241 | }; | |
255 |
|
242 | |||
256 |
|
243 | |||
257 | // Output handling. |
|
|||
258 |
|
||||
259 | CodeCell.prototype._handle_output = function (msg_type, content) { |
|
|||
260 | var json = {}; |
|
|||
261 | json.output_type = msg_type; |
|
|||
262 | if (msg_type === "stream") { |
|
|||
263 | json.text = content.data; |
|
|||
264 | json.stream = content.name; |
|
|||
265 | } else if (msg_type === "display_data") { |
|
|||
266 | json = this.convert_mime_types(json, content.data); |
|
|||
267 | } else if (msg_type === "pyout") { |
|
|||
268 | json.prompt_number = content.execution_count; |
|
|||
269 | json = this.convert_mime_types(json, content.data); |
|
|||
270 | } else if (msg_type === "pyerr") { |
|
|||
271 | json.ename = content.ename; |
|
|||
272 | json.evalue = content.evalue; |
|
|||
273 | json.traceback = content.traceback; |
|
|||
274 | }; |
|
|||
275 | // append with dynamic=true |
|
|||
276 | this.append_output(json, true); |
|
|||
277 | }; |
|
|||
278 |
|
||||
279 |
|
||||
280 | CodeCell.prototype.convert_mime_types = function (json, data) { |
|
|||
281 | if (data['text/plain'] !== undefined) { |
|
|||
282 | json.text = data['text/plain']; |
|
|||
283 | }; |
|
|||
284 | if (data['text/html'] !== undefined) { |
|
|||
285 | json.html = data['text/html']; |
|
|||
286 | }; |
|
|||
287 | if (data['image/svg+xml'] !== undefined) { |
|
|||
288 | json.svg = data['image/svg+xml']; |
|
|||
289 | }; |
|
|||
290 | if (data['image/png'] !== undefined) { |
|
|||
291 | json.png = data['image/png']; |
|
|||
292 | }; |
|
|||
293 | if (data['image/jpeg'] !== undefined) { |
|
|||
294 | json.jpeg = data['image/jpeg']; |
|
|||
295 | }; |
|
|||
296 | if (data['text/latex'] !== undefined) { |
|
|||
297 | json.latex = data['text/latex']; |
|
|||
298 | }; |
|
|||
299 | if (data['application/json'] !== undefined) { |
|
|||
300 | json.json = data['application/json']; |
|
|||
301 | }; |
|
|||
302 | if (data['application/javascript'] !== undefined) { |
|
|||
303 | json.javascript = data['application/javascript']; |
|
|||
304 | } |
|
|||
305 | return json; |
|
|||
306 | }; |
|
|||
307 |
|
||||
308 |
|
||||
309 | CodeCell.prototype.append_output = function (json, dynamic) { |
|
|||
310 | // If dynamic is true, javascript output will be eval'd. |
|
|||
311 | this.expand(); |
|
|||
312 | this.flush_clear_timeout(); |
|
|||
313 | if (json.output_type === 'pyout') { |
|
|||
314 | this.append_pyout(json, dynamic); |
|
|||
315 | } else if (json.output_type === 'pyerr') { |
|
|||
316 | this.append_pyerr(json); |
|
|||
317 | } else if (json.output_type === 'display_data') { |
|
|||
318 | this.append_display_data(json, dynamic); |
|
|||
319 | } else if (json.output_type === 'stream') { |
|
|||
320 | this.append_stream(json); |
|
|||
321 | }; |
|
|||
322 | this.outputs.push(json); |
|
|||
323 | }; |
|
|||
324 |
|
||||
325 |
|
||||
326 | CodeCell.prototype.create_output_area = function () { |
|
|||
327 | var oa = $("<div/>").addClass("hbox output_area"); |
|
|||
328 | oa.append($('<div/>').addClass('prompt')); |
|
|||
329 | return oa; |
|
|||
330 | }; |
|
|||
331 |
|
||||
332 |
|
||||
333 | CodeCell.prototype.append_pyout = function (json, dynamic) { |
|
|||
334 | var n = json.prompt_number || ' '; |
|
|||
335 | var toinsert = this.create_output_area(); |
|
|||
336 | toinsert.find('div.prompt').addClass('output_prompt').html('Out[' + n + ']:'); |
|
|||
337 | this.append_mime_type(json, toinsert, dynamic); |
|
|||
338 | this.element.find('div.output').append(toinsert); |
|
|||
339 | // If we just output latex, typeset it. |
|
|||
340 | if ((json.latex !== undefined) || (json.html !== undefined)) { |
|
|||
341 | this.typeset(); |
|
|||
342 | }; |
|
|||
343 | }; |
|
|||
344 |
|
||||
345 |
|
||||
346 | CodeCell.prototype.append_pyerr = function (json) { |
|
|||
347 | var tb = json.traceback; |
|
|||
348 | if (tb !== undefined && tb.length > 0) { |
|
|||
349 | var s = ''; |
|
|||
350 | var len = tb.length; |
|
|||
351 | for (var i=0; i<len; i++) { |
|
|||
352 | s = s + tb[i] + '\n'; |
|
|||
353 | } |
|
|||
354 | s = s + '\n'; |
|
|||
355 | var toinsert = this.create_output_area(); |
|
|||
356 | this.append_text(s, toinsert); |
|
|||
357 | this.element.find('div.output').append(toinsert); |
|
|||
358 | }; |
|
|||
359 | }; |
|
|||
360 |
|
||||
361 |
|
||||
362 | CodeCell.prototype.append_stream = function (json) { |
|
|||
363 | // temporary fix: if stream undefined (json file written prior to this patch), |
|
|||
364 | // default to most likely stdout: |
|
|||
365 | if (json.stream == undefined){ |
|
|||
366 | json.stream = 'stdout'; |
|
|||
367 | } |
|
|||
368 | if (!utils.fixConsole(json.text)){ |
|
|||
369 | // fixConsole gives nothing (empty string, \r, etc.) |
|
|||
370 | // so don't append any elements, which might add undesirable space |
|
|||
371 | return; |
|
|||
372 | } |
|
|||
373 | var subclass = "output_"+json.stream; |
|
|||
374 | if (this.outputs.length > 0){ |
|
|||
375 | // have at least one output to consider |
|
|||
376 | var last = this.outputs[this.outputs.length-1]; |
|
|||
377 | if (last.output_type == 'stream' && json.stream == last.stream){ |
|
|||
378 | // latest output was in the same stream, |
|
|||
379 | // so append directly into its pre tag |
|
|||
380 | // escape ANSI & HTML specials: |
|
|||
381 | var text = utils.fixConsole(json.text); |
|
|||
382 | this.element.find('div.'+subclass).last().find('pre').append(text); |
|
|||
383 | return; |
|
|||
384 | } |
|
|||
385 | } |
|
|||
386 |
|
||||
387 | // If we got here, attach a new div |
|
|||
388 | var toinsert = this.create_output_area(); |
|
|||
389 | this.append_text(json.text, toinsert, "output_stream "+subclass); |
|
|||
390 | this.element.find('div.output').append(toinsert); |
|
|||
391 | }; |
|
|||
392 |
|
||||
393 |
|
||||
394 | CodeCell.prototype.append_display_data = function (json, dynamic) { |
|
|||
395 | var toinsert = this.create_output_area(); |
|
|||
396 | this.append_mime_type(json, toinsert, dynamic); |
|
|||
397 | this.element.find('div.output').append(toinsert); |
|
|||
398 | // If we just output latex, typeset it. |
|
|||
399 | if ( (json.latex !== undefined) || (json.html !== undefined) ) { |
|
|||
400 | this.typeset(); |
|
|||
401 | }; |
|
|||
402 | }; |
|
|||
403 |
|
||||
404 |
|
||||
405 | CodeCell.prototype.append_mime_type = function (json, element, dynamic) { |
|
|||
406 | if (json.javascript !== undefined && dynamic) { |
|
|||
407 | this.append_javascript(json.javascript, element, dynamic); |
|
|||
408 | } else if (json.html !== undefined) { |
|
|||
409 | this.append_html(json.html, element); |
|
|||
410 | } else if (json.latex !== undefined) { |
|
|||
411 | this.append_latex(json.latex, element); |
|
|||
412 | } else if (json.svg !== undefined) { |
|
|||
413 | this.append_svg(json.svg, element); |
|
|||
414 | } else if (json.png !== undefined) { |
|
|||
415 | this.append_png(json.png, element); |
|
|||
416 | } else if (json.jpeg !== undefined) { |
|
|||
417 | this.append_jpeg(json.jpeg, element); |
|
|||
418 | } else if (json.text !== undefined) { |
|
|||
419 | this.append_text(json.text, element); |
|
|||
420 | }; |
|
|||
421 | }; |
|
|||
422 |
|
||||
423 |
|
||||
424 | CodeCell.prototype.append_html = function (html, element) { |
|
|||
425 | var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_html rendered_html"); |
|
|||
426 | toinsert.append(html); |
|
|||
427 | element.append(toinsert); |
|
|||
428 | }; |
|
|||
429 |
|
||||
430 |
|
||||
431 | CodeCell.prototype.append_javascript = function (js, container) { |
|
|||
432 | // We just eval the JS code, element appears in the local scope. |
|
|||
433 | var element = $("<div/>").addClass("box_flex1 output_subarea"); |
|
|||
434 | var kernel = this.kernel; |
|
|||
435 | container.append(element); |
|
|||
436 | // Div for js shouldn't be drawn, as it will add empty height to the area. |
|
|||
437 | container.hide(); |
|
|||
438 | // If the Javascript appends content to `element` that should be drawn, then |
|
|||
439 | // it must also call `container.show()`. |
|
|||
440 | eval(js); |
|
|||
441 | } |
|
|||
442 |
|
||||
443 |
|
||||
444 | CodeCell.prototype.append_text = function (data, element, extra_class) { |
|
|||
445 | var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_text"); |
|
|||
446 | // escape ANSI & HTML specials in plaintext: |
|
|||
447 | data = utils.fixConsole(data); |
|
|||
448 | if (extra_class){ |
|
|||
449 | toinsert.addClass(extra_class); |
|
|||
450 | } |
|
|||
451 | toinsert.append($("<pre/>").html(data)); |
|
|||
452 | element.append(toinsert); |
|
|||
453 | }; |
|
|||
454 |
|
||||
455 |
|
||||
456 | CodeCell.prototype.append_svg = function (svg, element) { |
|
|||
457 | var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_svg"); |
|
|||
458 | toinsert.append(svg); |
|
|||
459 | element.append(toinsert); |
|
|||
460 | }; |
|
|||
461 |
|
||||
462 |
|
||||
463 | CodeCell.prototype.append_png = function (png, element) { |
|
|||
464 | var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_png"); |
|
|||
465 | toinsert.append($("<img/>").attr('src','data:image/png;base64,'+png)); |
|
|||
466 | element.append(toinsert); |
|
|||
467 | }; |
|
|||
468 |
|
||||
469 |
|
||||
470 | CodeCell.prototype.append_jpeg = function (jpeg, element) { |
|
|||
471 | var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_jpeg"); |
|
|||
472 | toinsert.append($("<img/>").attr('src','data:image/jpeg;base64,'+jpeg)); |
|
|||
473 | element.append(toinsert); |
|
|||
474 | }; |
|
|||
475 |
|
||||
476 |
|
||||
477 | CodeCell.prototype.append_latex = function (latex, element) { |
|
|||
478 | // This method cannot do the typesetting because the latex first has to |
|
|||
479 | // be on the page. |
|
|||
480 | var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_latex"); |
|
|||
481 | toinsert.append(latex); |
|
|||
482 | element.append(toinsert); |
|
|||
483 | }; |
|
|||
484 |
|
||||
485 |
|
||||
486 | CodeCell.prototype._handle_clear_output = function (content) { |
|
|||
487 | this.clear_output(content.stdout, content.stderr, content.other); |
|
|||
488 | } |
|
|||
489 |
|
||||
490 |
|
||||
491 | CodeCell.prototype.clear_output = function (stdout, stderr, other) { |
|
244 | CodeCell.prototype.clear_output = function (stdout, stderr, other) { | |
492 | var that = this; |
|
245 | this.output_area.clear_output(stdout, stderr, other); | |
493 | if (this.clear_out_timeout != null){ |
|
|||
494 | // fire previous pending clear *immediately* |
|
|||
495 | clearTimeout(this.clear_out_timeout); |
|
|||
496 | this.clear_out_timeout = null; |
|
|||
497 | this.clear_output_callback(this._clear_stdout, this._clear_stderr, this._clear_other); |
|
|||
498 | } |
|
|||
499 | // store flags for flushing the timeout |
|
|||
500 | this._clear_stdout = stdout; |
|
|||
501 | this._clear_stderr = stderr; |
|
|||
502 | this._clear_other = other; |
|
|||
503 | this.clear_out_timeout = setTimeout(function() { |
|
|||
504 | // really clear timeout only after a short delay |
|
|||
505 | // this reduces flicker in 'clear_output; print' cases |
|
|||
506 | that.clear_out_timeout = null; |
|
|||
507 | that._clear_stdout = that._clear_stderr = that._clear_other = null; |
|
|||
508 | that.clear_output_callback(stdout, stderr, other); |
|
|||
509 | }, 500 |
|
|||
510 | ); |
|
|||
511 | }; |
|
246 | }; | |
512 |
|
247 | |||
513 |
|
248 | |||
514 | CodeCell.prototype.clear_output_callback = function (stdout, stderr, other) { |
|
|||
515 | var output_div = this.element.find("div.output"); |
|
|||
516 |
|
||||
517 | if (stdout && stderr && other){ |
|
|||
518 | // clear all, no need for logic |
|
|||
519 | output_div.html(""); |
|
|||
520 | this.outputs = []; |
|
|||
521 | return; |
|
|||
522 | } |
|
|||
523 | // remove html output |
|
|||
524 | // each output_subarea that has an identifying class is in an output_area |
|
|||
525 | // which is the element to be removed. |
|
|||
526 | if (stdout) { |
|
|||
527 | output_div.find("div.output_stdout").parent().remove(); |
|
|||
528 | } |
|
|||
529 | if (stderr) { |
|
|||
530 | output_div.find("div.output_stderr").parent().remove(); |
|
|||
531 | } |
|
|||
532 | if (other) { |
|
|||
533 | output_div.find("div.output_subarea").not("div.output_stderr").not("div.output_stdout").parent().remove(); |
|
|||
534 | } |
|
|||
535 |
|
||||
536 | // remove cleared outputs from JSON list: |
|
|||
537 | for (var i = this.outputs.length - 1; i >= 0; i--) { |
|
|||
538 | var out = this.outputs[i]; |
|
|||
539 | var output_type = out.output_type; |
|
|||
540 | if (output_type == "display_data" && other) { |
|
|||
541 | this.outputs.splice(i,1); |
|
|||
542 | } else if (output_type == "stream") { |
|
|||
543 | if (stdout && out.stream == "stdout") { |
|
|||
544 | this.outputs.splice(i,1); |
|
|||
545 | } else if (stderr && out.stream == "stderr") { |
|
|||
546 | this.outputs.splice(i,1); |
|
|||
547 | } |
|
|||
548 | } |
|
|||
549 | } |
|
|||
550 | }; |
|
|||
551 |
|
||||
552 |
|
||||
553 | CodeCell.prototype.flush_clear_timeout = function() { |
|
|||
554 | var output_div = this.element.find('div.output'); |
|
|||
555 | if (this.clear_out_timeout){ |
|
|||
556 | clearTimeout(this.clear_out_timeout); |
|
|||
557 | this.clear_out_timeout = null; |
|
|||
558 | this.clear_output_callback(this._clear_stdout, this._clear_stderr, this._clear_other); |
|
|||
559 | }; |
|
|||
560 | } |
|
|||
561 |
|
||||
562 |
|
||||
563 | // JSON serialization |
|
249 | // JSON serialization | |
564 |
|
250 | |||
565 | CodeCell.prototype.fromJSON = function (data) { |
|
251 | CodeCell.prototype.fromJSON = function (data) { | |
@@ -572,11 +258,7 b' var IPython = (function (IPython) {' | |||||
572 | } else { |
|
258 | } else { | |
573 | this.set_input_prompt(); |
|
259 | this.set_input_prompt(); | |
574 | }; |
|
260 | }; | |
575 | var len = data.outputs.length; |
|
261 | this.output_area.fromJSON(data.outputs); | |
576 | for (var i=0; i<len; i++) { |
|
|||
577 | // append with dynamic=false. |
|
|||
578 | this.append_output(data.outputs[i], false); |
|
|||
579 | }; |
|
|||
580 | if (data.collapsed !== undefined) { |
|
262 | if (data.collapsed !== undefined) { | |
581 | if (data.collapsed) { |
|
263 | if (data.collapsed) { | |
582 | this.collapse(); |
|
264 | this.collapse(); | |
@@ -595,11 +277,7 b' var IPython = (function (IPython) {' | |||||
595 | if (this.input_prompt_number) { |
|
277 | if (this.input_prompt_number) { | |
596 | data.prompt_number = this.input_prompt_number; |
|
278 | data.prompt_number = this.input_prompt_number; | |
597 | }; |
|
279 | }; | |
598 |
var outputs = |
|
280 | var outputs = this.output_area.toJSON(); | |
599 | var len = this.outputs.length; |
|
|||
600 | for (var i=0; i<len; i++) { |
|
|||
601 | outputs[i] = this.outputs[i]; |
|
|||
602 | }; |
|
|||
603 | data.outputs = outputs; |
|
281 | data.outputs = outputs; | |
604 | data.language = 'python'; |
|
282 | data.language = 'python'; | |
605 | data.collapsed = this.collapsed; |
|
283 | data.collapsed = this.collapsed; |
@@ -220,6 +220,7 b' data-notebook-id={{notebook_id}}' | |||||
220 | <script src="{{ static_url("js/utils.js") }}" type="text/javascript" charset="utf-8"></script> |
|
220 | <script src="{{ static_url("js/utils.js") }}" type="text/javascript" charset="utf-8"></script> | |
221 | <script src="{{ static_url("js/layoutmanager.js") }}" type="text/javascript" charset="utf-8"></script> |
|
221 | <script src="{{ static_url("js/layoutmanager.js") }}" type="text/javascript" charset="utf-8"></script> | |
222 | <script src="{{ static_url("js/initmathjax.js") }}" type="text/javascript" charset="utf-8"></script> |
|
222 | <script src="{{ static_url("js/initmathjax.js") }}" type="text/javascript" charset="utf-8"></script> | |
|
223 | <script src="{{ static_url("js/outputarea.js") }}" type="text/javascript" charset="utf-8"></script> | |||
223 | <script src="{{ static_url("js/cell.js") }}" type="text/javascript" charset="utf-8"></script> |
|
224 | <script src="{{ static_url("js/cell.js") }}" type="text/javascript" charset="utf-8"></script> | |
224 | <script src="{{ static_url("js/codecell.js") }}" type="text/javascript" charset="utf-8"></script> |
|
225 | <script src="{{ static_url("js/codecell.js") }}" type="text/javascript" charset="utf-8"></script> | |
225 | <script src="{{ static_url("js/completer.js") }}" type="text/javascript" charset="utf-8"></script> |
|
226 | <script src="{{ static_url("js/completer.js") }}" type="text/javascript" charset="utf-8"></script> |
@@ -70,6 +70,7 b' data-notebook-id={{notebook_id}}' | |||||
70 | <script src="{{ static_url("js/events.js") }}" type="text/javascript" charset="utf-8"></script> |
|
70 | <script src="{{ static_url("js/events.js") }}" type="text/javascript" charset="utf-8"></script> | |
71 | <script src="{{ static_url("js/utils.js") }}" type="text/javascript" charset="utf-8"></script> |
|
71 | <script src="{{ static_url("js/utils.js") }}" type="text/javascript" charset="utf-8"></script> | |
72 | <script src="{{ static_url("js/initmathjax.js") }}" type="text/javascript" charset="utf-8"></script> |
|
72 | <script src="{{ static_url("js/initmathjax.js") }}" type="text/javascript" charset="utf-8"></script> | |
|
73 | <script src="{{ static_url("js/outputarea.js") }}" type="text/javascript" charset="utf-8"></script> | |||
73 | <script src="{{ static_url("js/cell.js") }}" type="text/javascript" charset="utf-8"></script> |
|
74 | <script src="{{ static_url("js/cell.js") }}" type="text/javascript" charset="utf-8"></script> | |
74 | <script src="{{ static_url("js/codecell.js") }}" type="text/javascript" charset="utf-8"></script> |
|
75 | <script src="{{ static_url("js/codecell.js") }}" type="text/javascript" charset="utf-8"></script> | |
75 | <script src="{{ static_url("js/textcell.js") }}" type="text/javascript" charset="utf-8"></script> |
|
76 | <script src="{{ static_url("js/textcell.js") }}" type="text/javascript" charset="utf-8"></script> |
General Comments 0
You need to be logged in to leave comments.
Login now