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