##// END OF EJS Templates
Handle carriage return characters ("\r") in HTML notebook output....
Michael Droettboom -
Show More
@@ -1,306 +1,306 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 // CodeCell
9 // CodeCell
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 var key = IPython.utils.keycodes;
16 var key = IPython.utils.keycodes;
17
17
18 var CodeCell = function (kernel) {
18 var CodeCell = function (kernel) {
19 // The kernel doesn't have to be set at creation time, in that case
19 // The kernel doesn't have to be set at creation time, in that case
20 // it will be null and set_kernel has to be called later.
20 // it will be null and set_kernel has to be called later.
21 this.kernel = kernel || null;
21 this.kernel = kernel || null;
22 this.code_mirror = null;
22 this.code_mirror = null;
23 this.input_prompt_number = null;
23 this.input_prompt_number = null;
24 this.tooltip_on_tab = true;
24 this.tooltip_on_tab = true;
25 IPython.Cell.apply(this, arguments);
25 IPython.Cell.apply(this, arguments);
26 };
26 };
27
27
28
28
29 CodeCell.prototype = new IPython.Cell();
29 CodeCell.prototype = new IPython.Cell();
30
30
31
31
32 CodeCell.prototype.create_element = function () {
32 CodeCell.prototype.create_element = function () {
33 var cell = $('<div></div>').addClass('cell border-box-sizing code_cell vbox');
33 var cell = $('<div></div>').addClass('cell border-box-sizing code_cell vbox');
34 cell.attr('tabindex','2');
34 cell.attr('tabindex','2');
35 var input = $('<div></div>').addClass('input hbox');
35 var input = $('<div></div>').addClass('input hbox');
36 input.append($('<div/>').addClass('prompt input_prompt'));
36 input.append($('<div/>').addClass('prompt input_prompt'));
37 var input_area = $('<div/>').addClass('input_area box-flex1');
37 var input_area = $('<div/>').addClass('input_area box-flex1');
38 this.code_mirror = CodeMirror(input_area.get(0), {
38 this.code_mirror = CodeMirror(input_area.get(0), {
39 indentUnit : 4,
39 indentUnit : 4,
40 mode: 'python',
40 mode: 'python',
41 theme: 'ipython',
41 theme: 'ipython',
42 readOnly: this.read_only,
42 readOnly: this.read_only,
43 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
43 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
44 });
44 });
45 input.append(input_area);
45 input.append(input_area);
46 var output = $('<div></div>');
46 var output = $('<div></div>');
47 cell.append(input).append(output);
47 cell.append(input).append(output);
48 this.element = cell;
48 this.element = cell;
49 this.output_area = new IPython.OutputArea(output, true);
49 this.output_area = new IPython.OutputArea(output, true);
50
50
51 // construct a completer only if class exist
51 // construct a completer only if class exist
52 // otherwise no print view
52 // otherwise no print view
53 if (IPython.Completer !== undefined)
53 if (IPython.Completer !== undefined)
54 {
54 {
55 this.completer = new IPython.Completer(this);
55 this.completer = new IPython.Completer(this);
56 }
56 }
57 };
57 };
58
58
59 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
59 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
60 // This method gets called in CodeMirror's onKeyDown/onKeyPress
60 // This method gets called in CodeMirror's onKeyDown/onKeyPress
61 // handlers and is used to provide custom key handling. Its return
61 // handlers and is used to provide custom key handling. Its return
62 // value is used to determine if CodeMirror should ignore the event:
62 // value is used to determine if CodeMirror should ignore the event:
63 // true = ignore, false = don't ignore.
63 // true = ignore, false = don't ignore.
64
64
65 if (this.read_only){
65 if (this.read_only){
66 return false;
66 return false;
67 }
67 }
68
68
69 var that = this;
69 var that = this;
70 // whatever key is pressed, first, cancel the tooltip request before
70 // whatever key is pressed, first, cancel the tooltip request before
71 // they are sent, and remove tooltip if any, except for tab again
71 // they are sent, and remove tooltip if any, except for tab again
72 if (event.type === 'keydown' && event.which != key.TAB ) {
72 if (event.type === 'keydown' && event.which != key.TAB ) {
73 IPython.tooltip.remove_and_cancel_tooltip();
73 IPython.tooltip.remove_and_cancel_tooltip();
74 };
74 };
75
75
76 var cur = editor.getCursor();
76 var cur = editor.getCursor();
77
77
78 if (event.keyCode === key.ENTER && (event.shiftKey || event.ctrlKey)) {
78 if (event.keyCode === key.ENTER && (event.shiftKey || event.ctrlKey)) {
79 // Always ignore shift-enter in CodeMirror as we handle it.
79 // Always ignore shift-enter in CodeMirror as we handle it.
80 return true;
80 return true;
81 } else if (event.which === 40 && event.type === 'keypress' && IPython.tooltip.time_before_tooltip >= 0) {
81 } else if (event.which === 40 && event.type === 'keypress' && IPython.tooltip.time_before_tooltip >= 0) {
82 // triger on keypress (!) otherwise inconsistent event.which depending on plateform
82 // triger on keypress (!) otherwise inconsistent event.which depending on plateform
83 // browser and keyboard layout !
83 // browser and keyboard layout !
84 // Pressing '(' , request tooltip, don't forget to reappend it
84 // Pressing '(' , request tooltip, don't forget to reappend it
85 IPython.tooltip.pending(that);
85 IPython.tooltip.pending(that);
86 } else if (event.which === key.UPARROW && event.type === 'keydown') {
86 } else if (event.which === key.UPARROW && event.type === 'keydown') {
87 // If we are not at the top, let CM handle the up arrow and
87 // If we are not at the top, let CM handle the up arrow and
88 // prevent the global keydown handler from handling it.
88 // prevent the global keydown handler from handling it.
89 if (!that.at_top()) {
89 if (!that.at_top()) {
90 event.stop();
90 event.stop();
91 return false;
91 return false;
92 } else {
92 } else {
93 return true;
93 return true;
94 };
94 };
95 } else if (event.which === key.ESC) {
95 } else if (event.which === key.ESC) {
96 IPython.tooltip.remove_and_cancel_tooltip(true);
96 IPython.tooltip.remove_and_cancel_tooltip(true);
97 return true;
97 return true;
98 } else if (event.which === key.DOWNARROW && event.type === 'keydown') {
98 } else if (event.which === key.DOWNARROW && event.type === 'keydown') {
99 // If we are not at the bottom, let CM handle the down arrow and
99 // If we are not at the bottom, let CM handle the down arrow and
100 // prevent the global keydown handler from handling it.
100 // prevent the global keydown handler from handling it.
101 if (!that.at_bottom()) {
101 if (!that.at_bottom()) {
102 event.stop();
102 event.stop();
103 return false;
103 return false;
104 } else {
104 } else {
105 return true;
105 return true;
106 };
106 };
107 } else if (event.keyCode === key.TAB && event.type == 'keydown') {
107 } else if (event.keyCode === key.TAB && event.type == 'keydown') {
108 // Tab completion.
108 // Tab completion.
109 //Do not trim here because of tooltip
109 //Do not trim here because of tooltip
110 var pre_cursor = editor.getRange({line:cur.line,ch:0},cur);
110 var pre_cursor = editor.getRange({line:cur.line,ch:0},cur);
111 if (pre_cursor.trim() === "") {
111 if (pre_cursor.trim() === "") {
112 // Don't autocomplete if the part of the line before the cursor
112 // Don't autocomplete if the part of the line before the cursor
113 // is empty. In this case, let CodeMirror handle indentation.
113 // is empty. In this case, let CodeMirror handle indentation.
114 return false;
114 return false;
115 } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && that.tooltip_on_tab ) {
115 } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && that.tooltip_on_tab ) {
116 IPython.tooltip.request(that);
116 IPython.tooltip.request(that);
117 // Prevent the event from bubbling up.
117 // Prevent the event from bubbling up.
118 event.stop();
118 event.stop();
119 // Prevent CodeMirror from handling the tab.
119 // Prevent CodeMirror from handling the tab.
120 return true;
120 return true;
121 } else {
121 } else {
122 event.stop();
122 event.stop();
123 this.completer.startCompletion();
123 this.completer.startCompletion();
124 return true;
124 return true;
125 };
125 };
126 } else if (event.keyCode === key.BACKSPACE && event.type == 'keydown') {
126 } else if (event.keyCode === key.BACKSPACE && event.type == 'keydown') {
127 // If backspace and the line ends with 4 spaces, remove them.
127 // If backspace and the line ends with 4 spaces, remove them.
128 var line = editor.getLine(cur.line);
128 var line = editor.getLine(cur.line);
129 var ending = line.slice(-4);
129 var ending = line.slice(-4);
130 if (ending === ' ') {
130 if (ending === ' ') {
131 editor.replaceRange('',
131 editor.replaceRange('',
132 {line: cur.line, ch: cur.ch-4},
132 {line: cur.line, ch: cur.ch-4},
133 {line: cur.line, ch: cur.ch}
133 {line: cur.line, ch: cur.ch}
134 );
134 );
135 event.stop();
135 event.stop();
136 return true;
136 return true;
137 } else {
137 } else {
138 return false;
138 return false;
139 };
139 };
140 } else {
140 } else {
141 // keypress/keyup also trigger on TAB press, and we don't want to
141 // keypress/keyup also trigger on TAB press, and we don't want to
142 // use those to disable tab completion.
142 // use those to disable tab completion.
143 return false;
143 return false;
144 };
144 };
145 return false;
145 return false;
146 };
146 };
147
147
148
148
149 // Kernel related calls.
149 // Kernel related calls.
150
150
151 CodeCell.prototype.set_kernel = function (kernel) {
151 CodeCell.prototype.set_kernel = function (kernel) {
152 this.kernel = kernel;
152 this.kernel = kernel;
153 }
153 }
154
154
155
155
156 CodeCell.prototype.execute = function () {
156 CodeCell.prototype.execute = function () {
157 this.output_area.clear_output(true, true, true);
157 this.output_area.clear_output(true, true, true);
158 this.set_input_prompt('*');
158 this.set_input_prompt('*');
159 this.element.addClass("running");
159 this.element.addClass("running");
160 var callbacks = {
160 var callbacks = {
161 'execute_reply': $.proxy(this._handle_execute_reply, this),
161 'execute_reply': $.proxy(this._handle_execute_reply, this),
162 'output': $.proxy(this.output_area.handle_output, this.output_area),
162 'output': $.proxy(this.output_area.handle_output, this.output_area),
163 'clear_output': $.proxy(this.output_area.handle_clear_output, this.output_area),
163 'clear_output': $.proxy(this.output_area.handle_clear_output, this.output_area),
164 'set_next_input': $.proxy(this._handle_set_next_input, this)
164 'set_next_input': $.proxy(this._handle_set_next_input, this)
165 };
165 };
166 var msg_id = this.kernel.execute(this.get_text(), callbacks, {silent: false});
166 var msg_id = this.kernel.execute(this.get_text(), callbacks, {silent: false});
167 };
167 };
168
168
169
169
170 CodeCell.prototype._handle_execute_reply = function (content) {
170 CodeCell.prototype._handle_execute_reply = function (content) {
171 this.set_input_prompt(content.execution_count);
171 this.set_input_prompt(content.execution_count);
172 this.element.removeClass("running");
172 this.element.removeClass("running");
173 $([IPython.events]).trigger('set_dirty.Notebook', {'value': true});
173 $([IPython.events]).trigger('set_dirty.Notebook', {'value': true});
174 }
174 }
175
175
176 CodeCell.prototype._handle_set_next_input = function (text) {
176 CodeCell.prototype._handle_set_next_input = function (text) {
177 var data = {'cell': this, 'text': text}
177 var data = {'cell': this, 'text': text}
178 $([IPython.events]).trigger('set_next_input.Notebook', data);
178 $([IPython.events]).trigger('set_next_input.Notebook', data);
179 }
179 }
180
180
181 // Basic cell manipulation.
181 // Basic cell manipulation.
182
182
183 CodeCell.prototype.select = function () {
183 CodeCell.prototype.select = function () {
184 IPython.Cell.prototype.select.apply(this);
184 IPython.Cell.prototype.select.apply(this);
185 this.code_mirror.refresh();
185 this.code_mirror.refresh();
186 this.code_mirror.focus();
186 this.code_mirror.focus();
187 // We used to need an additional refresh() after the focus, but
187 // We used to need an additional refresh() after the focus, but
188 // it appears that this has been fixed in CM. This bug would show
188 // it appears that this has been fixed in CM. This bug would show
189 // up on FF when a newly loaded markdown cell was edited.
189 // up on FF when a newly loaded markdown cell was edited.
190 };
190 };
191
191
192
192
193 CodeCell.prototype.select_all = function () {
193 CodeCell.prototype.select_all = function () {
194 var start = {line: 0, ch: 0};
194 var start = {line: 0, ch: 0};
195 var nlines = this.code_mirror.lineCount();
195 var nlines = this.code_mirror.lineCount();
196 var last_line = this.code_mirror.getLine(nlines-1);
196 var last_line = this.code_mirror.getLine(nlines-1);
197 var end = {line: nlines-1, ch: last_line.length};
197 var end = {line: nlines-1, ch: last_line.length};
198 this.code_mirror.setSelection(start, end);
198 this.code_mirror.setSelection(start, end);
199 };
199 };
200
200
201
201
202 CodeCell.prototype.collapse = function () {
202 CodeCell.prototype.collapse = function () {
203 this.output_area.collapse();
203 this.output_area.collapse();
204 };
204 };
205
205
206
206
207 CodeCell.prototype.expand = function () {
207 CodeCell.prototype.expand = function () {
208 this.output_area.expand();
208 this.output_area.expand();
209 };
209 };
210
210
211
211
212 CodeCell.prototype.toggle_output = function () {
212 CodeCell.prototype.toggle_output = function () {
213 this.output_area.toggle_output();
213 this.output_area.toggle_output();
214 };
214 };
215
215
216
216
217 CodeCell.prototype.set_input_prompt = function (number) {
217 CodeCell.prototype.set_input_prompt = function (number) {
218 this.input_prompt_number = number;
218 this.input_prompt_number = number;
219 var ns = number || "&nbsp;";
219 var ns = number || "&nbsp;";
220 this.element.find('div.input_prompt').html('In&nbsp;[' + ns + ']:');
220 this.element.find('div.input_prompt').html('In&nbsp;[' + ns + ']:');
221 };
221 };
222
222
223
223
224 CodeCell.prototype.clear_input = function () {
224 CodeCell.prototype.clear_input = function () {
225 this.code_mirror.setValue('');
225 this.code_mirror.setValue('');
226 };
226 };
227
227
228
228
229 CodeCell.prototype.get_text = function () {
229 CodeCell.prototype.get_text = function () {
230 return this.code_mirror.getValue();
230 return this.code_mirror.getValue();
231 };
231 };
232
232
233
233
234 CodeCell.prototype.set_text = function (code) {
234 CodeCell.prototype.set_text = function (code) {
235 return this.code_mirror.setValue(code);
235 return this.code_mirror.setValue(code);
236 };
236 };
237
237
238
238
239 CodeCell.prototype.at_top = function () {
239 CodeCell.prototype.at_top = function () {
240 var cursor = this.code_mirror.getCursor();
240 var cursor = this.code_mirror.getCursor();
241 if (cursor.line === 0) {
241 if (cursor.line === 0) {
242 return true;
242 return true;
243 } else {
243 } else {
244 return false;
244 return false;
245 }
245 }
246 };
246 };
247
247
248
248
249 CodeCell.prototype.at_bottom = function () {
249 CodeCell.prototype.at_bottom = function () {
250 var cursor = this.code_mirror.getCursor();
250 var cursor = this.code_mirror.getCursor();
251 if (cursor.line === (this.code_mirror.lineCount()-1)) {
251 if (cursor.line === (this.code_mirror.lineCount()-1)) {
252 return true;
252 return true;
253 } else {
253 } else {
254 return false;
254 return false;
255 }
255 }
256 };
256 };
257
257
258
258
259 CodeCell.prototype.clear_output = function (stdout, stderr, other) {
259 CodeCell.prototype.clear_output = function (stdout, stderr, other) {
260 this.output_area.clear_output(stdout, stderr, other);
260 this.output_area.clear_output(stdout, stderr, other);
261 };
261 };
262
262
263
263
264 // JSON serialization
264 // JSON serialization
265
265
266 CodeCell.prototype.fromJSON = function (data) {
266 CodeCell.prototype.fromJSON = function (data) {
267 if (data.cell_type === 'code') {
267 if (data.cell_type === 'code') {
268 if (data.input !== undefined) {
268 if (data.input !== undefined) {
269 this.set_text(data.input);
269 this.set_text(data.input);
270 }
270 }
271 if (data.prompt_number !== undefined) {
271 if (data.prompt_number !== undefined) {
272 this.set_input_prompt(data.prompt_number);
272 this.set_input_prompt(data.prompt_number);
273 } else {
273 } else {
274 this.set_input_prompt();
274 this.set_input_prompt();
275 };
275 };
276 this.output_area.fromJSON(data.outputs);
276 this.output_area.fromJSON(data.outputs);
277 if (data.collapsed !== undefined) {
277 if (data.collapsed !== undefined) {
278 if (data.collapsed) {
278 if (data.collapsed) {
279 this.collapse();
279 this.collapse();
280 } else {
280 } else {
281 this.expand();
281 this.expand();
282 };
282 };
283 };
283 };
284 };
284 };
285 };
285 };
286
286
287
287
288 CodeCell.prototype.toJSON = function () {
288 CodeCell.prototype.toJSON = function () {
289 var data = {};
289 var data = {};
290 data.input = this.get_text();
290 data.input = this.get_text();
291 data.cell_type = 'code';
291 data.cell_type = 'code';
292 if (this.input_prompt_number) {
292 if (this.input_prompt_number) {
293 data.prompt_number = this.input_prompt_number;
293 data.prompt_number = this.input_prompt_number;
294 };
294 };
295 var outputs = this.output_area.toJSON();
295 var outputs = this.output_area.toJSON();
296 data.outputs = outputs;
296 data.outputs = outputs;
297 data.language = 'python';
297 data.language = 'python';
298 data.collapsed = this.collapsed;
298 data.collapsed = this.collapsed;
299 return data;
299 return data;
300 };
300 };
301
301
302
302
303 IPython.CodeCell = CodeCell;
303 IPython.CodeCell = CodeCell;
304
304
305 return IPython;
305 return IPython;
306 }(IPython));
306 }(IPython));
@@ -1,403 +1,408 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.element = $(selector);
19 this.element = $(selector);
20 this.outputs = [];
20 this.outputs = [];
21 this.collapsed = false;
21 this.collapsed = false;
22 this.clear_out_timeout = null;
22 this.clear_out_timeout = null;
23 if (prompt_area === undefined) {
23 if (prompt_area === undefined) {
24 this.prompt_area = true;
24 this.prompt_area = true;
25 } else {
25 } else {
26 this.prompt_area = prompt_area;
26 this.prompt_area = prompt_area;
27 };
27 };
28 this.style();
28 this.style();
29 };
29 };
30
30
31
31
32 OutputArea.prototype.style = function () {
32 OutputArea.prototype.style = function () {
33 this.element.addClass('output vbox');
33 this.element.addClass('output vbox');
34 this.collapse();
34 this.collapse();
35 };
35 };
36
36
37
37
38 OutputArea.prototype.collapse = function () {
38 OutputArea.prototype.collapse = function () {
39 if (!this.collapsed) {
39 if (!this.collapsed) {
40 this.element.hide();
40 this.element.hide();
41 this.collapsed = true;
41 this.collapsed = true;
42 };
42 };
43 };
43 };
44
44
45
45
46 OutputArea.prototype.expand = function () {
46 OutputArea.prototype.expand = function () {
47 if (this.collapsed) {
47 if (this.collapsed) {
48 this.element.show();
48 this.element.show();
49 this.collapsed = false;
49 this.collapsed = false;
50 };
50 };
51 };
51 };
52
52
53
53
54 OutputArea.prototype.toggle_output = function () {
54 OutputArea.prototype.toggle_output = function () {
55 if (this.collapsed) {
55 if (this.collapsed) {
56 this.expand();
56 this.expand();
57 } else {
57 } else {
58 this.collapse();
58 this.collapse();
59 };
59 };
60 };
60 };
61
61
62
62
63 // typeset with MathJax if MathJax is available
63 // typeset with MathJax if MathJax is available
64 OutputArea.prototype.typeset = function () {
64 OutputArea.prototype.typeset = function () {
65 if (window.MathJax){
65 if (window.MathJax){
66 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
66 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
67 }
67 }
68 };
68 };
69
69
70
70
71 OutputArea.prototype.handle_output = function (msg_type, content) {
71 OutputArea.prototype.handle_output = function (msg_type, content) {
72 var json = {};
72 var json = {};
73 json.output_type = msg_type;
73 json.output_type = msg_type;
74 if (msg_type === "stream") {
74 if (msg_type === "stream") {
75 json.text = content.data;
75 json.text = content.data;
76 json.stream = content.name;
76 json.stream = content.name;
77 } else if (msg_type === "display_data") {
77 } else if (msg_type === "display_data") {
78 json = this.convert_mime_types(json, content.data);
78 json = this.convert_mime_types(json, content.data);
79 } else if (msg_type === "pyout") {
79 } else if (msg_type === "pyout") {
80 json.prompt_number = content.execution_count;
80 json.prompt_number = content.execution_count;
81 json = this.convert_mime_types(json, content.data);
81 json = this.convert_mime_types(json, content.data);
82 } else if (msg_type === "pyerr") {
82 } else if (msg_type === "pyerr") {
83 json.ename = content.ename;
83 json.ename = content.ename;
84 json.evalue = content.evalue;
84 json.evalue = content.evalue;
85 json.traceback = content.traceback;
85 json.traceback = content.traceback;
86 };
86 };
87 // append with dynamic=true
87 // append with dynamic=true
88 this.append_output(json, true);
88 this.append_output(json, true);
89 };
89 };
90
90
91
91
92 OutputArea.prototype.convert_mime_types = function (json, data) {
92 OutputArea.prototype.convert_mime_types = function (json, data) {
93 if (data['text/plain'] !== undefined) {
93 if (data['text/plain'] !== undefined) {
94 json.text = data['text/plain'];
94 json.text = data['text/plain'];
95 };
95 };
96 if (data['text/html'] !== undefined) {
96 if (data['text/html'] !== undefined) {
97 json.html = data['text/html'];
97 json.html = data['text/html'];
98 };
98 };
99 if (data['image/svg+xml'] !== undefined) {
99 if (data['image/svg+xml'] !== undefined) {
100 json.svg = data['image/svg+xml'];
100 json.svg = data['image/svg+xml'];
101 };
101 };
102 if (data['image/png'] !== undefined) {
102 if (data['image/png'] !== undefined) {
103 json.png = data['image/png'];
103 json.png = data['image/png'];
104 };
104 };
105 if (data['image/jpeg'] !== undefined) {
105 if (data['image/jpeg'] !== undefined) {
106 json.jpeg = data['image/jpeg'];
106 json.jpeg = data['image/jpeg'];
107 };
107 };
108 if (data['text/latex'] !== undefined) {
108 if (data['text/latex'] !== undefined) {
109 json.latex = data['text/latex'];
109 json.latex = data['text/latex'];
110 };
110 };
111 if (data['application/json'] !== undefined) {
111 if (data['application/json'] !== undefined) {
112 json.json = data['application/json'];
112 json.json = data['application/json'];
113 };
113 };
114 if (data['application/javascript'] !== undefined) {
114 if (data['application/javascript'] !== undefined) {
115 json.javascript = data['application/javascript'];
115 json.javascript = data['application/javascript'];
116 }
116 }
117 return json;
117 return json;
118 };
118 };
119
119
120
120
121 OutputArea.prototype.append_output = function (json, dynamic) {
121 OutputArea.prototype.append_output = function (json, dynamic) {
122 // If dynamic is true, javascript output will be eval'd.
122 // If dynamic is true, javascript output will be eval'd.
123 this.expand();
123 this.expand();
124 this.flush_clear_timeout();
124 this.flush_clear_timeout();
125 if (json.output_type === 'pyout') {
125 if (json.output_type === 'pyout') {
126 this.append_pyout(json, dynamic);
126 this.append_pyout(json, dynamic);
127 } else if (json.output_type === 'pyerr') {
127 } else if (json.output_type === 'pyerr') {
128 this.append_pyerr(json);
128 this.append_pyerr(json);
129 } else if (json.output_type === 'display_data') {
129 } else if (json.output_type === 'display_data') {
130 this.append_display_data(json, dynamic);
130 this.append_display_data(json, dynamic);
131 } else if (json.output_type === 'stream') {
131 } else if (json.output_type === 'stream') {
132 this.append_stream(json);
132 this.append_stream(json);
133 };
133 };
134 this.outputs.push(json);
134 this.outputs.push(json);
135 };
135 };
136
136
137
137
138 OutputArea.prototype.create_output_area = function () {
138 OutputArea.prototype.create_output_area = function () {
139 var oa = $("<div/>").addClass("hbox output_area");
139 var oa = $("<div/>").addClass("hbox output_area");
140 if (this.prompt_area) {
140 if (this.prompt_area) {
141 oa.append($('<div/>').addClass('prompt'));
141 oa.append($('<div/>').addClass('prompt'));
142 }
142 }
143 return oa;
143 return oa;
144 };
144 };
145
145
146
146
147 OutputArea.prototype.append_pyout = function (json, dynamic) {
147 OutputArea.prototype.append_pyout = function (json, dynamic) {
148 var n = json.prompt_number || ' ';
148 var n = json.prompt_number || ' ';
149 var toinsert = this.create_output_area();
149 var toinsert = this.create_output_area();
150 if (this.prompt_area) {
150 if (this.prompt_area) {
151 toinsert.find('div.prompt').addClass('output_prompt').html('Out[' + n + ']:');
151 toinsert.find('div.prompt').addClass('output_prompt').html('Out[' + n + ']:');
152 }
152 }
153 this.append_mime_type(json, toinsert, dynamic);
153 this.append_mime_type(json, toinsert, dynamic);
154 this.element.append(toinsert);
154 this.element.append(toinsert);
155 // If we just output latex, typeset it.
155 // If we just output latex, typeset it.
156 if ((json.latex !== undefined) || (json.html !== undefined)) {
156 if ((json.latex !== undefined) || (json.html !== undefined)) {
157 this.typeset();
157 this.typeset();
158 };
158 };
159 };
159 };
160
160
161
161
162 OutputArea.prototype.append_pyerr = function (json) {
162 OutputArea.prototype.append_pyerr = function (json) {
163 var tb = json.traceback;
163 var tb = json.traceback;
164 if (tb !== undefined && tb.length > 0) {
164 if (tb !== undefined && tb.length > 0) {
165 var s = '';
165 var s = '';
166 var len = tb.length;
166 var len = tb.length;
167 for (var i=0; i<len; i++) {
167 for (var i=0; i<len; i++) {
168 s = s + tb[i] + '\n';
168 s = s + tb[i] + '\n';
169 }
169 }
170 s = s + '\n';
170 s = s + '\n';
171 var toinsert = this.create_output_area();
171 var toinsert = this.create_output_area();
172 this.append_text(s, toinsert);
172 this.append_text(s, toinsert);
173 this.element.append(toinsert);
173 this.element.append(toinsert);
174 };
174 };
175 };
175 };
176
176
177
177
178 OutputArea.prototype.append_stream = function (json) {
178 OutputArea.prototype.append_stream = function (json) {
179 // temporary fix: if stream undefined (json file written prior to this patch),
179 // temporary fix: if stream undefined (json file written prior to this patch),
180 // default to most likely stdout:
180 // default to most likely stdout:
181 if (json.stream == undefined){
181 if (json.stream == undefined){
182 json.stream = 'stdout';
182 json.stream = 'stdout';
183 }
183 }
184 if (!utils.fixConsole(json.text)){
184 var text = utils.fixConsole(json.text);
185 // fixConsole gives nothing (empty string, \r, etc.)
186 // so don't append any elements, which might add undesirable space
187 return;
188 }
189 var subclass = "output_"+json.stream;
185 var subclass = "output_"+json.stream;
190 if (this.outputs.length > 0){
186 if (this.outputs.length > 0){
191 // have at least one output to consider
187 // have at least one output to consider
192 var last = this.outputs[this.outputs.length-1];
188 var last = this.outputs[this.outputs.length-1];
193 if (last.output_type == 'stream' && json.stream == last.stream){
189 if (last.output_type == 'stream' && json.stream == last.stream){
194 // latest output was in the same stream,
190 // latest output was in the same stream,
195 // so append directly into its pre tag
191 // so append directly into its pre tag
196 // escape ANSI & HTML specials:
192 // escape ANSI & HTML specials:
197 var text = utils.fixConsole(json.text);
193 pre = this.element.find('div.'+subclass).last().find('pre');
198 this.element.find('div.'+subclass).last().find('pre').append(text);
194 html = utils.fixCarriageReturn(
195 pre.html() + utils.fixConsole(text));
196 pre.html(html);
199 return;
197 return;
200 }
198 }
201 }
199 }
202
200
201 if (!text.replace("\r", "")) {
202 // text is nothing (empty string, \r, etc.)
203 // so don't append any elements, which might add undesirable space
204 return;
205 }
206
203 // If we got here, attach a new div
207 // If we got here, attach a new div
204 var toinsert = this.create_output_area();
208 var toinsert = this.create_output_area();
205 this.append_text(json.text, toinsert, "output_stream "+subclass);
209 this.append_text(text, toinsert, "output_stream "+subclass);
206 this.element.append(toinsert);
210 this.element.append(toinsert);
207 };
211 };
208
212
209
213
210 OutputArea.prototype.append_display_data = function (json, dynamic) {
214 OutputArea.prototype.append_display_data = function (json, dynamic) {
211 var toinsert = this.create_output_area();
215 var toinsert = this.create_output_area();
212 this.append_mime_type(json, toinsert, dynamic);
216 this.append_mime_type(json, toinsert, dynamic);
213 this.element.append(toinsert);
217 this.element.append(toinsert);
214 // If we just output latex, typeset it.
218 // If we just output latex, typeset it.
215 if ( (json.latex !== undefined) || (json.html !== undefined) ) {
219 if ( (json.latex !== undefined) || (json.html !== undefined) ) {
216 this.typeset();
220 this.typeset();
217 };
221 };
218 };
222 };
219
223
220
224
221 OutputArea.prototype.append_mime_type = function (json, element, dynamic) {
225 OutputArea.prototype.append_mime_type = function (json, element, dynamic) {
222 if (json.javascript !== undefined && dynamic) {
226 if (json.javascript !== undefined && dynamic) {
223 this.append_javascript(json.javascript, element, dynamic);
227 this.append_javascript(json.javascript, element, dynamic);
224 } else if (json.html !== undefined) {
228 } else if (json.html !== undefined) {
225 this.append_html(json.html, element);
229 this.append_html(json.html, element);
226 } else if (json.latex !== undefined) {
230 } else if (json.latex !== undefined) {
227 this.append_latex(json.latex, element);
231 this.append_latex(json.latex, element);
228 } else if (json.svg !== undefined) {
232 } else if (json.svg !== undefined) {
229 this.append_svg(json.svg, element);
233 this.append_svg(json.svg, element);
230 } else if (json.png !== undefined) {
234 } else if (json.png !== undefined) {
231 this.append_png(json.png, element);
235 this.append_png(json.png, element);
232 } else if (json.jpeg !== undefined) {
236 } else if (json.jpeg !== undefined) {
233 this.append_jpeg(json.jpeg, element);
237 this.append_jpeg(json.jpeg, element);
234 } else if (json.text !== undefined) {
238 } else if (json.text !== undefined) {
235 this.append_text(json.text, element);
239 this.append_text(json.text, element);
236 };
240 };
237 };
241 };
238
242
239
243
240 OutputArea.prototype.append_html = function (html, element) {
244 OutputArea.prototype.append_html = function (html, element) {
241 var toinsert = $("<div/>").addClass("box-flex1 output_subarea output_html rendered_html");
245 var toinsert = $("<div/>").addClass("box-flex1 output_subarea output_html rendered_html");
242 toinsert.append(html);
246 toinsert.append(html);
243 element.append(toinsert);
247 element.append(toinsert);
244 };
248 };
245
249
246
250
247 OutputArea.prototype.append_javascript = function (js, container) {
251 OutputArea.prototype.append_javascript = function (js, container) {
248 // We just eval the JS code, element appears in the local scope.
252 // We just eval the JS code, element appears in the local scope.
249 var element = $("<div/>").addClass("box-flex1 output_subarea");
253 var element = $("<div/>").addClass("box-flex1 output_subarea");
250 container.append(element);
254 container.append(element);
251 // Div for js shouldn't be drawn, as it will add empty height to the area.
255 // Div for js shouldn't be drawn, as it will add empty height to the area.
252 container.hide();
256 container.hide();
253 // If the Javascript appends content to `element` that should be drawn, then
257 // If the Javascript appends content to `element` that should be drawn, then
254 // it must also call `container.show()`.
258 // it must also call `container.show()`.
255 eval(js);
259 eval(js);
256 }
260 }
257
261
258
262
259 OutputArea.prototype.append_text = function (data, element, extra_class) {
263 OutputArea.prototype.append_text = function (data, element, extra_class) {
260 var toinsert = $("<div/>").addClass("box-flex1 output_subarea output_text");
264 var toinsert = $("<div/>").addClass("box-flex1 output_subarea output_text");
261 // escape ANSI & HTML specials in plaintext:
265 // escape ANSI & HTML specials in plaintext:
262 data = utils.fixConsole(data);
266 data = utils.fixConsole(data);
267 data = utils.fixCarriageReturn(data);
263 if (extra_class){
268 if (extra_class){
264 toinsert.addClass(extra_class);
269 toinsert.addClass(extra_class);
265 }
270 }
266 toinsert.append($("<pre/>").html(data));
271 toinsert.append($("<pre/>").html(data));
267 element.append(toinsert);
272 element.append(toinsert);
268 };
273 };
269
274
270
275
271 OutputArea.prototype.append_svg = function (svg, element) {
276 OutputArea.prototype.append_svg = function (svg, element) {
272 var toinsert = $("<div/>").addClass("box-flex1 output_subarea output_svg");
277 var toinsert = $("<div/>").addClass("box-flex1 output_subarea output_svg");
273 toinsert.append(svg);
278 toinsert.append(svg);
274 element.append(toinsert);
279 element.append(toinsert);
275 };
280 };
276
281
277
282
278 OutputArea.prototype.append_png = function (png, element) {
283 OutputArea.prototype.append_png = function (png, element) {
279 var toinsert = $("<div/>").addClass("box-flex1 output_subarea output_png");
284 var toinsert = $("<div/>").addClass("box-flex1 output_subarea output_png");
280 toinsert.append($("<img/>").attr('src','data:image/png;base64,'+png));
285 toinsert.append($("<img/>").attr('src','data:image/png;base64,'+png));
281 element.append(toinsert);
286 element.append(toinsert);
282 };
287 };
283
288
284
289
285 OutputArea.prototype.append_jpeg = function (jpeg, element) {
290 OutputArea.prototype.append_jpeg = function (jpeg, element) {
286 var toinsert = $("<div/>").addClass("box-flex1 output_subarea output_jpeg");
291 var toinsert = $("<div/>").addClass("box-flex1 output_subarea output_jpeg");
287 toinsert.append($("<img/>").attr('src','data:image/jpeg;base64,'+jpeg));
292 toinsert.append($("<img/>").attr('src','data:image/jpeg;base64,'+jpeg));
288 element.append(toinsert);
293 element.append(toinsert);
289 };
294 };
290
295
291
296
292 OutputArea.prototype.append_latex = function (latex, element) {
297 OutputArea.prototype.append_latex = function (latex, element) {
293 // This method cannot do the typesetting because the latex first has to
298 // This method cannot do the typesetting because the latex first has to
294 // be on the page.
299 // be on the page.
295 var toinsert = $("<div/>").addClass("box-flex1 output_subarea output_latex");
300 var toinsert = $("<div/>").addClass("box-flex1 output_subarea output_latex");
296 toinsert.append(latex);
301 toinsert.append(latex);
297 element.append(toinsert);
302 element.append(toinsert);
298 };
303 };
299
304
300
305
301 OutputArea.prototype.handle_clear_output = function (content) {
306 OutputArea.prototype.handle_clear_output = function (content) {
302 this.clear_output(content.stdout, content.stderr, content.other);
307 this.clear_output(content.stdout, content.stderr, content.other);
303 }
308 }
304
309
305
310
306 OutputArea.prototype.clear_output = function (stdout, stderr, other) {
311 OutputArea.prototype.clear_output = function (stdout, stderr, other) {
307 var that = this;
312 var that = this;
308 if (this.clear_out_timeout != null){
313 if (this.clear_out_timeout != null){
309 // fire previous pending clear *immediately*
314 // fire previous pending clear *immediately*
310 clearTimeout(this.clear_out_timeout);
315 clearTimeout(this.clear_out_timeout);
311 this.clear_out_timeout = null;
316 this.clear_out_timeout = null;
312 this.clear_output_callback(this._clear_stdout, this._clear_stderr, this._clear_other);
317 this.clear_output_callback(this._clear_stdout, this._clear_stderr, this._clear_other);
313 }
318 }
314 // store flags for flushing the timeout
319 // store flags for flushing the timeout
315 this._clear_stdout = stdout;
320 this._clear_stdout = stdout;
316 this._clear_stderr = stderr;
321 this._clear_stderr = stderr;
317 this._clear_other = other;
322 this._clear_other = other;
318 this.clear_out_timeout = setTimeout(function() {
323 this.clear_out_timeout = setTimeout(function() {
319 // really clear timeout only after a short delay
324 // really clear timeout only after a short delay
320 // this reduces flicker in 'clear_output; print' cases
325 // this reduces flicker in 'clear_output; print' cases
321 that.clear_out_timeout = null;
326 that.clear_out_timeout = null;
322 that._clear_stdout = that._clear_stderr = that._clear_other = null;
327 that._clear_stdout = that._clear_stderr = that._clear_other = null;
323 that.clear_output_callback(stdout, stderr, other);
328 that.clear_output_callback(stdout, stderr, other);
324 }, 500
329 }, 500
325 );
330 );
326 };
331 };
327
332
328
333
329 OutputArea.prototype.clear_output_callback = function (stdout, stderr, other) {
334 OutputArea.prototype.clear_output_callback = function (stdout, stderr, other) {
330 var output_div = this.element;
335 var output_div = this.element;
331
336
332 if (stdout && stderr && other){
337 if (stdout && stderr && other){
333 // clear all, no need for logic
338 // clear all, no need for logic
334 output_div.html("");
339 output_div.html("");
335 this.outputs = [];
340 this.outputs = [];
336 return;
341 return;
337 }
342 }
338 // remove html output
343 // remove html output
339 // each output_subarea that has an identifying class is in an output_area
344 // each output_subarea that has an identifying class is in an output_area
340 // which is the element to be removed.
345 // which is the element to be removed.
341 if (stdout) {
346 if (stdout) {
342 output_div.find("div.output_stdout").parent().remove();
347 output_div.find("div.output_stdout").parent().remove();
343 }
348 }
344 if (stderr) {
349 if (stderr) {
345 output_div.find("div.output_stderr").parent().remove();
350 output_div.find("div.output_stderr").parent().remove();
346 }
351 }
347 if (other) {
352 if (other) {
348 output_div.find("div.output_subarea").not("div.output_stderr").not("div.output_stdout").parent().remove();
353 output_div.find("div.output_subarea").not("div.output_stderr").not("div.output_stdout").parent().remove();
349 }
354 }
350
355
351 // remove cleared outputs from JSON list:
356 // remove cleared outputs from JSON list:
352 for (var i = this.outputs.length - 1; i >= 0; i--) {
357 for (var i = this.outputs.length - 1; i >= 0; i--) {
353 var out = this.outputs[i];
358 var out = this.outputs[i];
354 var output_type = out.output_type;
359 var output_type = out.output_type;
355 if (output_type == "display_data" && other) {
360 if (output_type == "display_data" && other) {
356 this.outputs.splice(i,1);
361 this.outputs.splice(i,1);
357 } else if (output_type == "stream") {
362 } else if (output_type == "stream") {
358 if (stdout && out.stream == "stdout") {
363 if (stdout && out.stream == "stdout") {
359 this.outputs.splice(i,1);
364 this.outputs.splice(i,1);
360 } else if (stderr && out.stream == "stderr") {
365 } else if (stderr && out.stream == "stderr") {
361 this.outputs.splice(i,1);
366 this.outputs.splice(i,1);
362 }
367 }
363 }
368 }
364 }
369 }
365 };
370 };
366
371
367
372
368 OutputArea.prototype.flush_clear_timeout = function() {
373 OutputArea.prototype.flush_clear_timeout = function() {
369 var output_div = this.element;
374 var output_div = this.element;
370 if (this.clear_out_timeout){
375 if (this.clear_out_timeout){
371 clearTimeout(this.clear_out_timeout);
376 clearTimeout(this.clear_out_timeout);
372 this.clear_out_timeout = null;
377 this.clear_out_timeout = null;
373 this.clear_output_callback(this._clear_stdout, this._clear_stderr, this._clear_other);
378 this.clear_output_callback(this._clear_stdout, this._clear_stderr, this._clear_other);
374 };
379 };
375 }
380 }
376
381
377
382
378 // JSON serialization
383 // JSON serialization
379
384
380 OutputArea.prototype.fromJSON = function (outputs) {
385 OutputArea.prototype.fromJSON = function (outputs) {
381 var len = outputs.length;
386 var len = outputs.length;
382 for (var i=0; i<len; i++) {
387 for (var i=0; i<len; i++) {
383 // append with dynamic=false.
388 // append with dynamic=false.
384 this.append_output(outputs[i], false);
389 this.append_output(outputs[i], false);
385 };
390 };
386 };
391 };
387
392
388
393
389 OutputArea.prototype.toJSON = function () {
394 OutputArea.prototype.toJSON = function () {
390 var outputs = [];
395 var outputs = [];
391 var len = this.outputs.length;
396 var len = this.outputs.length;
392 for (var i=0; i<len; i++) {
397 for (var i=0; i<len; i++) {
393 outputs[i] = this.outputs[i];
398 outputs[i] = this.outputs[i];
394 };
399 };
395 return outputs;
400 return outputs;
396 };
401 };
397
402
398
403
399 IPython.OutputArea = OutputArea;
404 IPython.OutputArea = OutputArea;
400
405
401 return IPython;
406 return IPython;
402
407
403 }(IPython));
408 }(IPython));
@@ -1,130 +1,130 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 // Pager
9 // Pager
10 //============================================================================
10 //============================================================================
11
11
12 var IPython = (function (IPython) {
12 var IPython = (function (IPython) {
13
13
14 var utils = IPython.utils;
14 var utils = IPython.utils;
15
15
16 var Pager = function (pager_selector, pager_splitter_selector) {
16 var Pager = function (pager_selector, pager_splitter_selector) {
17 this.pager_element = $(pager_selector);
17 this.pager_element = $(pager_selector);
18 var that = this;
18 var that = this;
19 this.percentage_height = 0.40;
19 this.percentage_height = 0.40;
20 this.pager_splitter_element = $(pager_splitter_selector)
20 this.pager_splitter_element = $(pager_splitter_selector)
21 .draggable({
21 .draggable({
22 containment: 'window',
22 containment: 'window',
23 axis:'y',
23 axis:'y',
24 helper: null ,
24 helper: null ,
25 drag: function(event, ui) {
25 drag: function(event, ui) {
26 // recalculate the amount of space the pager should take
26 // recalculate the amount of space the pager should take
27 var pheight = ($(body).height()-event.clientY-4);
27 var pheight = ($(body).height()-event.clientY-4);
28 var downprct = pheight/IPython.layout_manager.app_height();
28 var downprct = pheight/IPython.layout_manager.app_height();
29 downprct = Math.min(0.9, downprct);
29 downprct = Math.min(0.9, downprct);
30 if (downprct < 0.1) {
30 if (downprct < 0.1) {
31 that.percentage_height = 0.1;
31 that.percentage_height = 0.1;
32 that.collapse({'duration':0});
32 that.collapse({'duration':0});
33 } else if (downprct > 0.2) {
33 } else if (downprct > 0.2) {
34 that.percentage_height = downprct;
34 that.percentage_height = downprct;
35 that.expand({'duration':0});
35 that.expand({'duration':0});
36 }
36 }
37 IPython.layout_manager.do_resize();
37 IPython.layout_manager.do_resize();
38 }
38 }
39 });
39 });
40 this.expanded = false;
40 this.expanded = false;
41 this.style();
41 this.style();
42 this.bind_events();
42 this.bind_events();
43 };
43 };
44
44
45 Pager.prototype.style = function () {
45 Pager.prototype.style = function () {
46 this.pager_splitter_element.addClass('border-box-sizing ui-widget ui-state-default');
46 this.pager_splitter_element.addClass('border-box-sizing ui-widget ui-state-default');
47 this.pager_element.addClass('border-box-sizing ui-widget');
47 this.pager_element.addClass('border-box-sizing ui-widget');
48 this.pager_splitter_element.attr('title', 'Click to Show/Hide pager area, drag to Resize');
48 this.pager_splitter_element.attr('title', 'Click to Show/Hide pager area, drag to Resize');
49 };
49 };
50
50
51
51
52 Pager.prototype.bind_events = function () {
52 Pager.prototype.bind_events = function () {
53 var that = this;
53 var that = this;
54
54
55 this.pager_element.bind('collapse_pager', function (event, extrap) {
55 this.pager_element.bind('collapse_pager', function (event, extrap) {
56 time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast';
56 time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast';
57 that.pager_element.hide(time);
57 that.pager_element.hide(time);
58 });
58 });
59
59
60 this.pager_element.bind('expand_pager', function (event, extrap) {
60 this.pager_element.bind('expand_pager', function (event, extrap) {
61 time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast';
61 time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast';
62 that.pager_element.show(time);
62 that.pager_element.show(time);
63 });
63 });
64
64
65 this.pager_splitter_element.hover(
65 this.pager_splitter_element.hover(
66 function () {
66 function () {
67 that.pager_splitter_element.addClass('ui-state-hover');
67 that.pager_splitter_element.addClass('ui-state-hover');
68 },
68 },
69 function () {
69 function () {
70 that.pager_splitter_element.removeClass('ui-state-hover');
70 that.pager_splitter_element.removeClass('ui-state-hover');
71 }
71 }
72 );
72 );
73
73
74 this.pager_splitter_element.click(function () {
74 this.pager_splitter_element.click(function () {
75 that.toggle();
75 that.toggle();
76 });
76 });
77
77
78 $([IPython.events]).on('open_with_text.Pager', function (event, data) {
78 $([IPython.events]).on('open_with_text.Pager', function (event, data) {
79 if (data.text.trim() !== '') {
79 if (data.text.trim() !== '') {
80 that.clear();
80 that.clear();
81 that.expand();
81 that.expand();
82 that.append_text(data.text);
82 that.append_text(data.text);
83 };
83 };
84 });
84 });
85 };
85 };
86
86
87
87
88 Pager.prototype.collapse = function (extrap) {
88 Pager.prototype.collapse = function (extrap) {
89 if (this.expanded === true) {
89 if (this.expanded === true) {
90 this.expanded = false;
90 this.expanded = false;
91 this.pager_element.add($('div#notebook')).trigger('collapse_pager', extrap);
91 this.pager_element.add($('div#notebook')).trigger('collapse_pager', extrap);
92 };
92 };
93 };
93 };
94
94
95
95
96 Pager.prototype.expand = function (extrap) {
96 Pager.prototype.expand = function (extrap) {
97 if (this.expanded !== true) {
97 if (this.expanded !== true) {
98 this.expanded = true;
98 this.expanded = true;
99 this.pager_element.add($('div#notebook')).trigger('expand_pager', extrap);
99 this.pager_element.add($('div#notebook')).trigger('expand_pager', extrap);
100 };
100 };
101 };
101 };
102
102
103
103
104 Pager.prototype.toggle = function () {
104 Pager.prototype.toggle = function () {
105 if (this.expanded === true) {
105 if (this.expanded === true) {
106 this.collapse();
106 this.collapse();
107 } else {
107 } else {
108 this.expand();
108 this.expand();
109 };
109 };
110 };
110 };
111
111
112
112
113 Pager.prototype.clear = function (text) {
113 Pager.prototype.clear = function (text) {
114 this.pager_element.empty();
114 this.pager_element.empty();
115 };
115 };
116
116
117
117
118 Pager.prototype.append_text = function (text) {
118 Pager.prototype.append_text = function (text) {
119 var toinsert = $("<div/>").addClass("output_area output_stream");
119 var toinsert = $("<div/>").addClass("output_area output_stream");
120 toinsert.append($('<pre/>').html(utils.fixConsole(text)));
120 toinsert.append($('<pre/>').html(utils.fixCarriageReturn(utils.fixConsole(text))));
121 this.pager_element.append(toinsert);
121 this.pager_element.append(toinsert);
122 };
122 };
123
123
124
124
125 IPython.Pager = Pager;
125 IPython.Pager = Pager;
126
126
127 return IPython;
127 return IPython;
128
128
129 }(IPython));
129 }(IPython));
130
130
@@ -1,138 +1,138 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 // Utilities
9 // Utilities
10 //============================================================================
10 //============================================================================
11
11
12 IPython.namespace('IPython.utils');
12 IPython.namespace('IPython.utils');
13
13
14 IPython.utils = (function (IPython) {
14 IPython.utils = (function (IPython) {
15
15
16 var uuid = function () {
16 var uuid = function () {
17 // http://www.ietf.org/rfc/rfc4122.txt
17 // http://www.ietf.org/rfc/rfc4122.txt
18 var s = [];
18 var s = [];
19 var hexDigits = "0123456789ABCDEF";
19 var hexDigits = "0123456789ABCDEF";
20 for (var i = 0; i < 32; i++) {
20 for (var i = 0; i < 32; i++) {
21 s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
21 s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
22 }
22 }
23 s[12] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
23 s[12] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
24 s[16] = hexDigits.substr((s[16] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
24 s[16] = hexDigits.substr((s[16] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
25
25
26 var uuid = s.join("");
26 var uuid = s.join("");
27 return uuid;
27 return uuid;
28 };
28 };
29
29
30
30
31 //Fix raw text to parse correctly in crazy XML
31 //Fix raw text to parse correctly in crazy XML
32 function xmlencode(string) {
32 function xmlencode(string) {
33 return string.replace(/\&/g,'&'+'amp;')
33 return string.replace(/\&/g,'&'+'amp;')
34 .replace(/</g,'&'+'lt;')
34 .replace(/</g,'&'+'lt;')
35 .replace(/>/g,'&'+'gt;')
35 .replace(/>/g,'&'+'gt;')
36 .replace(/\'/g,'&'+'apos;')
36 .replace(/\'/g,'&'+'apos;')
37 .replace(/\"/g,'&'+'quot;')
37 .replace(/\"/g,'&'+'quot;')
38 .replace(/`/g,'&'+'#96;');
38 .replace(/`/g,'&'+'#96;');
39 }
39 }
40
40
41
41
42 //Map from terminal commands to CSS classes
42 //Map from terminal commands to CSS classes
43 ansi_colormap = {
43 ansi_colormap = {
44 "30":"ansiblack", "31":"ansired",
44 "30":"ansiblack", "31":"ansired",
45 "32":"ansigreen", "33":"ansiyellow",
45 "32":"ansigreen", "33":"ansiyellow",
46 "34":"ansiblue", "35":"ansipurple","36":"ansicyan",
46 "34":"ansiblue", "35":"ansipurple","36":"ansicyan",
47 "37":"ansigrey", "01":"ansibold"
47 "37":"ansigrey", "01":"ansibold"
48 };
48 };
49
49
50 // Transform ANI color escape codes into HTML <span> tags with css
50 // Transform ANSI color escape codes into HTML <span> tags with css
51 // classes listed in the above ansi_colormap object. The actual color used
51 // classes listed in the above ansi_colormap object. The actual color used
52 // are set in the css file.
52 // are set in the css file.
53 function fixConsole(txt) {
53 function fixConsole(txt) {
54 txt = xmlencode(txt);
54 txt = xmlencode(txt);
55 var re = /\033\[([\dA-Fa-f;]*?)m/;
55 var re = /\033\[([\dA-Fa-f;]*?)m/;
56 var opened = false;
56 var opened = false;
57 var cmds = [];
57 var cmds = [];
58 var opener = "";
58 var opener = "";
59 var closer = "";
59 var closer = "";
60 // \r does nothing, so shouldn't be included
60 // \r does nothing, so shouldn't be included
61 txt = txt.replace('\r', '');
62 while (re.test(txt)) {
61 while (re.test(txt)) {
63 var cmds = txt.match(re)[1].split(";");
62 var cmds = txt.match(re)[1].split(";");
64 closer = opened?"</span>":"";
63 closer = opened?"</span>":"";
65 opened = cmds.length > 1 || cmds[0] != 0;
64 opened = cmds.length > 1 || cmds[0] != 0;
66 var rep = [];
65 var rep = [];
67 for (var i in cmds)
66 for (var i in cmds)
68 if (typeof(ansi_colormap[cmds[i]]) != "undefined")
67 if (typeof(ansi_colormap[cmds[i]]) != "undefined")
69 rep.push(ansi_colormap[cmds[i]]);
68 rep.push(ansi_colormap[cmds[i]]);
70 opener = rep.length > 0?"<span class=\""+rep.join(" ")+"\">":"";
69 opener = rep.length > 0?"<span class=\""+rep.join(" ")+"\">":"";
71 txt = txt.replace(re, closer + opener);
70 txt = txt.replace(re, closer + opener);
72 }
71 }
73 if (opened) txt += "</span>";
72 if (opened) txt += "</span>";
74 return txt;
73 return txt;
75 }
74 }
76
75
77 // Remove chunks that should be overridden by the effect of
76 // Remove chunks that should be overridden by the effect of
78 // carriage return characters
77 // carriage return characters
79 function fixCarriageReturn(txt) {
78 function fixCarriageReturn(txt) {
80 tmp = txt;
79 tmp = txt;
81 do {
80 do {
82 txt = tmp;
81 txt = tmp;
83 tmp = txt.replace(/^.*\r(?!\n)/gm, '');
82 tmp = txt.replace(/^.*\r(?!\n)/gm, '');
84 } while (tmp.length < txt.length);
83 } while (tmp.length < txt.length);
85 return txt;
84 return txt;
86 }
85 }
87
86
88 grow = function(element) {
87 grow = function(element) {
89 // Grow the cell by hand. This is used upon reloading from JSON, when the
88 // Grow the cell by hand. This is used upon reloading from JSON, when the
90 // autogrow handler is not called.
89 // autogrow handler is not called.
91 var dom = element.get(0);
90 var dom = element.get(0);
92 var lines_count = 0;
91 var lines_count = 0;
93 // modified split rule from
92 // modified split rule from
94 // http://stackoverflow.com/questions/2035910/how-to-get-the-number-of-lines-in-a-textarea/2036424#2036424
93 // http://stackoverflow.com/questions/2035910/how-to-get-the-number-of-lines-in-a-textarea/2036424#2036424
95 var lines = dom.value.split(/\r|\r\n|\n/);
94 var lines = dom.value.split(/\r|\r\n|\n/);
96 lines_count = lines.length;
95 lines_count = lines.length;
97 if (lines_count >= 1) {
96 if (lines_count >= 1) {
98 dom.rows = lines_count;
97 dom.rows = lines_count;
99 } else {
98 } else {
100 dom.rows = 1;
99 dom.rows = 1;
101 }
100 }
102 };
101 };
103
102
104 // some keycodes that seem to be platform/browser independant
103 // some keycodes that seem to be platform/browser independant
105 var keycodes ={
104 var keycodes ={
106 BACKSPACE: 8,
105 BACKSPACE: 8,
107 TAB : 9,
106 TAB : 9,
108 ENTER : 13,
107 ENTER : 13,
109 SHIFT : 16,
108 SHIFT : 16,
110 CTRL : 17,
109 CTRL : 17,
111 CONTROL : 17,
110 CONTROL : 17,
112 ALT : 18,
111 ALT : 18,
113 ESC : 27,
112 ESC : 27,
114 SPACE : 32,
113 SPACE : 32,
115 PGUP : 33,
114 PGUP : 33,
116 PGDOWN : 34,
115 PGDOWN : 34,
117 LEFT_ARROW: 37,
116 LEFT_ARROW: 37,
118 LEFTARROW: 37,
117 LEFTARROW: 37,
119 LEFT : 37,
118 LEFT : 37,
120 UP_ARROW : 38,
119 UP_ARROW : 38,
121 UPARROW : 38,
120 UPARROW : 38,
122 UP : 38,
121 UP : 38,
123 RIGHT_ARROW:39,
122 RIGHT_ARROW:39,
124 RIGHTARROW:39,
123 RIGHTARROW:39,
125 RIGHT : 39,
124 RIGHT : 39,
126 DOWN_ARROW: 40,
125 DOWN_ARROW: 40,
127 DOWNARROW: 40,
126 DOWNARROW: 40,
128 DOWN : 40,
127 DOWN : 40,
129 };
128 };
130
129
131 return {
130 return {
132 uuid : uuid,
131 uuid : uuid,
133 fixConsole : fixConsole,
132 fixConsole : fixConsole,
134 keycodes : keycodes,
133 keycodes : keycodes,
135 grow : grow,
134 grow : grow,
135 fixCarriageReturn : fixCarriageReturn
136 };
136 };
137
137
138 }(IPython));
138 }(IPython));
General Comments 0
You need to be logged in to leave comments. Login now