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