##// END OF EJS Templates
completer update code-miror on the fly...
Matthias BUSSONNIER -
Show More
@@ -1,461 +1,466 b''
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 background-color: white;
9 background-color: white;
10 /* This makes sure that the body covers the entire window and needs to
10 /* This makes sure that the body covers the entire window and needs to
11 be in a different element than the display: box in wrapper below */
11 be in a different element than the display: box in wrapper below */
12 position: absolute;
12 position: absolute;
13 left: 0px;
13 left: 0px;
14 right: 0px;
14 right: 0px;
15 top: 0px;
15 top: 0px;
16 bottom: 0px;
16 bottom: 0px;
17 overflow: hidden;
17 overflow: hidden;
18 }
18 }
19
19
20 span#save_widget {
20 span#save_widget {
21 position: static;
21 position: static;
22 left: 0px;
22 left: 0px;
23 padding: 5px 0px;
23 padding: 5px 0px;
24 margin: 0px 0px 0px 0px;
24 margin: 0px 0px 0px 0px;
25 }
25 }
26
26
27 span#quick_help_area {
27 span#quick_help_area {
28 position: static;
28 position: static;
29 padding: 5px 0px;
29 padding: 5px 0px;
30 margin: 0px 0px 0px 0px;
30 margin: 0px 0px 0px 0px;
31 }
31 }
32
32
33 input#notebook_name {
33 input#notebook_name {
34 height: 1em;
34 height: 1em;
35 line-height: 1em;
35 line-height: 1em;
36 padding: 5px;
36 padding: 5px;
37 }
37 }
38
38
39 span#kernel_status {
39 span#kernel_status {
40 position: absolute;
40 position: absolute;
41 padding: 8px 5px 5px 5px;
41 padding: 8px 5px 5px 5px;
42 right: 10px;
42 right: 10px;
43 font-weight: bold;
43 font-weight: bold;
44 }
44 }
45
45
46
46
47 .status_idle {
47 .status_idle {
48 color: gray;
48 color: gray;
49 visibility: hidden;
49 visibility: hidden;
50 }
50 }
51
51
52 .status_busy {
52 .status_busy {
53 color: red;
53 color: red;
54 }
54 }
55
55
56 .status_restarting {
56 .status_restarting {
57 color: black;
57 color: black;
58 }
58 }
59
59
60 div#left_panel {
60 div#left_panel {
61 overflow-y: auto;
61 overflow-y: auto;
62 top: 0px;
62 top: 0px;
63 left: 0px;
63 left: 0px;
64 margin: 0px;
64 margin: 0px;
65 padding: 0px;
65 padding: 0px;
66 position: absolute;
66 position: absolute;
67 }
67 }
68
68
69 div.section_header {
69 div.section_header {
70 padding: 5px;
70 padding: 5px;
71 }
71 }
72
72
73 div.section_header h3 {
73 div.section_header h3 {
74 display: inline;
74 display: inline;
75 }
75 }
76
76
77 div.section_content {
77 div.section_content {
78 padding: 5px;
78 padding: 5px;
79 }
79 }
80
80
81 span.section_row_buttons button {
81 span.section_row_buttons button {
82 width: 70px;
82 width: 70px;
83 }
83 }
84
84
85 span.section_row_buttons a {
85 span.section_row_buttons a {
86 width: 70px;
86 width: 70px;
87 }
87 }
88
88
89 .section_row {
89 .section_row {
90 margin: 5px 0px;
90 margin: 5px 0px;
91 }
91 }
92
92
93 .section_row_buttons {
93 .section_row_buttons {
94 float: right;
94 float: right;
95 }
95 }
96
96
97 #kernel_persist {
97 #kernel_persist {
98 float: right;
98 float: right;
99 }
99 }
100
100
101 .help_string {
101 .help_string {
102 float: right;
102 float: right;
103 width: 170px;
103 width: 170px;
104 padding: 0px 5px;
104 padding: 0px 5px;
105 text-align: left;
105 text-align: left;
106 font-size: 85%;
106 font-size: 85%;
107 }
107 }
108
108
109 .help_string_label {
109 .help_string_label {
110 float: right;
110 float: right;
111 font-size: 85%;
111 font-size: 85%;
112 }
112 }
113
113
114 #autoindent_span {
114 #autoindent_span {
115 float: right;
115 float: right;
116 }
116 }
117
117
118 #timebeforetooltip{
118 #timebeforetooltip{
119 margin-top:-3px;
119 margin-top:-3px;
120 text-align:right;
120 text-align:right;
121 }
121 }
122
122
123 #timebeforetooltip_span {
123 #timebeforetooltip_span {
124 float: right;
124 float: right;
125 padding: 0px 5px;
125 padding: 0px 5px;
126 font-size: 85%;
126 font-size: 85%;
127 }
127 }
128
128
129 #timebeforetooltip_label {
129 #timebeforetooltip_label {
130 float: right;
130 float: right;
131 text-align:right;
131 text-align:right;
132 font-size: 85%;
132 font-size: 85%;
133 }
133 }
134
134
135 #tooltipontab_span {
135 #tooltipontab_span {
136 float: right;
136 float: right;
137 }
137 }
138
138
139 #smartcompleter_span {
139 #smartcompleter_span {
140 float: right;
140 float: right;
141 }
141 }
142
142
143 .checkbox_label {
143 .checkbox_label {
144 font-size: 85%;
144 font-size: 85%;
145 float: right;
145 float: right;
146 padding: 0.3em;
146 padding: 0.3em;
147 }
147 }
148
148
149 .section_row_header {
149 .section_row_header {
150 float: left;
150 float: left;
151 font-size: 85%;
151 font-size: 85%;
152 padding: 0.4em 0em;
152 padding: 0.4em 0em;
153 font-weight: bold;
153 font-weight: bold;
154 }
154 }
155
155
156 span.button_label {
156 span.button_label {
157 padding: 0.2em 1em;
157 padding: 0.2em 1em;
158 font-size: 77%;
158 font-size: 77%;
159 float: right;
159 float: right;
160 }
160 }
161
161
162 /* This is needed because FF was adding a 2px margin top and bottom. */
162 /* This is needed because FF was adding a 2px margin top and bottom. */
163 .section_row .ui-button {
163 .section_row .ui-button {
164 margin-top: 0px;
164 margin-top: 0px;
165 margin-bottom: 0px;
165 margin-bottom: 0px;
166 }
166 }
167
167
168 #download_format {
168 #download_format {
169 float: right;
169 float: right;
170 font-size: 85%;
170 font-size: 85%;
171 width: 62px;
171 width: 62px;
172 margin: 1px 5px;
172 margin: 1px 5px;
173 }
173 }
174
174
175 div#left_panel_splitter {
175 div#left_panel_splitter {
176 width: 8px;
176 width: 8px;
177 top: 0px;
177 top: 0px;
178 left: 202px;
178 left: 202px;
179 margin: 0px;
179 margin: 0px;
180 padding: 0px;
180 padding: 0px;
181 position: absolute;
181 position: absolute;
182 }
182 }
183
183
184 div#notebook_panel {
184 div#notebook_panel {
185 /* The L margin will be set in the Javascript code*/
185 /* The L margin will be set in the Javascript code*/
186 margin: 0px 0px 0px 0px;
186 margin: 0px 0px 0px 0px;
187 padding: 0px;
187 padding: 0px;
188 }
188 }
189
189
190 div#notebook {
190 div#notebook {
191 overflow-y: scroll;
191 overflow-y: scroll;
192 overflow-x: auto;
192 overflow-x: auto;
193 width: 100%;
193 width: 100%;
194 /* This spaces the cell away from the edge of the notebook area */
194 /* This spaces the cell away from the edge of the notebook area */
195 padding: 5px 5px 15px 5px;
195 padding: 5px 5px 15px 5px;
196 margin: 0px
196 margin: 0px
197 background-color: white;
197 background-color: white;
198 }
198 }
199
199
200 div#pager_splitter {
200 div#pager_splitter {
201 height: 8px;
201 height: 8px;
202 }
202 }
203
203
204 div#pager {
204 div#pager {
205 padding: 15px;
205 padding: 15px;
206 overflow: auto;
206 overflow: auto;
207 }
207 }
208
208
209 div.cell {
209 div.cell {
210 width: 100%;
210 width: 100%;
211 padding: 5px 5px 5px 0px;
211 padding: 5px 5px 5px 0px;
212 /* This acts as a spacer between cells, that is outside the border */
212 /* This acts as a spacer between cells, that is outside the border */
213 margin: 2px 0px 2px 0px;
213 margin: 2px 0px 2px 0px;
214 }
214 }
215
215
216 div.code_cell {
216 div.code_cell {
217 background-color: white;
217 background-color: white;
218 }
218 }
219 /* any special styling for code cells that are currently running goes here */
219 /* any special styling for code cells that are currently running goes here */
220 div.code_cell.running {
220 div.code_cell.running {
221 }
221 }
222
222
223 div.prompt {
223 div.prompt {
224 /* This needs to be wide enough for 3 digit prompt numbers: In[100]: */
224 /* This needs to be wide enough for 3 digit prompt numbers: In[100]: */
225 width: 11ex;
225 width: 11ex;
226 /* This 0.4em is tuned to match the padding on the CodeMirror editor. */
226 /* This 0.4em is tuned to match the padding on the CodeMirror editor. */
227 padding: 0.4em;
227 padding: 0.4em;
228 margin: 0px;
228 margin: 0px;
229 font-family: monospace;
229 font-family: monospace;
230 text-align:right;
230 text-align:right;
231 }
231 }
232
232
233 div.input {
233 div.input {
234 page-break-inside: avoid;
234 page-break-inside: avoid;
235 }
235 }
236
236
237 /* input_area and input_prompt must match in top border and margin for alignment */
237 /* input_area and input_prompt must match in top border and margin for alignment */
238 div.input_area {
238 div.input_area {
239 color: black;
239 color: black;
240 border: 1px solid #ddd;
240 border: 1px solid #ddd;
241 border-radius: 3px;
241 border-radius: 3px;
242 background: #f7f7f7;
242 background: #f7f7f7;
243 }
243 }
244
244
245 div.input_prompt {
245 div.input_prompt {
246 color: navy;
246 color: navy;
247 border-top: 1px solid transparent;
247 border-top: 1px solid transparent;
248 }
248 }
249
249
250 div.output {
250 div.output {
251 /* This is a spacer between the input and output of each cell */
251 /* This is a spacer between the input and output of each cell */
252 margin-top: 5px;
252 margin-top: 5px;
253 }
253 }
254
254
255 div.output_prompt {
255 div.output_prompt {
256 color: darkred;
256 color: darkred;
257 }
257 }
258
258
259 /* This class is the outer container of all output sections. */
259 /* This class is the outer container of all output sections. */
260 div.output_area {
260 div.output_area {
261 padding: 0px;
261 padding: 0px;
262 page-break-inside: avoid;
262 page-break-inside: avoid;
263 }
263 }
264
264
265 /* This class is for the output subarea inside the output_area and after
265 /* This class is for the output subarea inside the output_area and after
266 the prompt div. */
266 the prompt div. */
267 div.output_subarea {
267 div.output_subarea {
268 padding: 0.4em 6.1em 0.4em 0.4em;
268 padding: 0.4em 6.1em 0.4em 0.4em;
269 }
269 }
270
270
271 /* The rest of the output_* classes are for special styling of the different
271 /* The rest of the output_* classes are for special styling of the different
272 output types */
272 output types */
273
273
274 /* all text output has this class: */
274 /* all text output has this class: */
275 div.output_text {
275 div.output_text {
276 text-align: left;
276 text-align: left;
277 color: black;
277 color: black;
278 font-family: monospace;
278 font-family: monospace;
279 }
279 }
280
280
281 /* stdout/stderr are 'text' as well as 'stream', but pyout/pyerr are *not* streams */
281 /* stdout/stderr are 'text' as well as 'stream', but pyout/pyerr are *not* streams */
282 div.output_stream {
282 div.output_stream {
283 padding-top: 0.0em;
283 padding-top: 0.0em;
284 padding-bottom: 0.0em;
284 padding-bottom: 0.0em;
285 }
285 }
286 div.output_stdout {
286 div.output_stdout {
287 }
287 }
288 div.output_stderr {
288 div.output_stderr {
289 background: #fdd; /* very light red background for stderr */
289 background: #fdd; /* very light red background for stderr */
290 }
290 }
291
291
292 div.output_latex {
292 div.output_latex {
293 text-align: left;
293 text-align: left;
294 color: black;
294 color: black;
295 }
295 }
296
296
297 div.output_html {
297 div.output_html {
298 }
298 }
299
299
300 div.output_png {
300 div.output_png {
301 }
301 }
302
302
303 div.output_jpeg {
303 div.output_jpeg {
304 }
304 }
305
305
306 div.text_cell {
306 div.text_cell {
307 background-color: white;
307 background-color: white;
308 }
308 }
309
309
310 div.text_cell_input {
310 div.text_cell_input {
311 color: black;
311 color: black;
312 }
312 }
313
313
314 div.text_cell_render {
314 div.text_cell_render {
315 font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
315 font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
316 outline: none;
316 outline: none;
317 resize: none;
317 resize: none;
318 width: inherit;
318 width: inherit;
319 border-style: none;
319 border-style: none;
320 padding: 5px;
320 padding: 5px;
321 color: black;
321 color: black;
322 }
322 }
323
323
324 .CodeMirror {
324 .CodeMirror {
325 line-height: 1.231; /* Changed from 1em to our global default */
325 line-height: 1.231; /* Changed from 1em to our global default */
326 }
326 }
327
327
328 .CodeMirror-scroll {
328 .CodeMirror-scroll {
329 height: auto; /* Changed to auto to autogrow */
329 height: auto; /* Changed to auto to autogrow */
330 /* The CodeMirror docs are a bit fuzzy on if overflow-y should be hidden or visible.*/
330 /* The CodeMirror docs are a bit fuzzy on if overflow-y should be hidden or visible.*/
331 /* We have found that if it is visible, vertical scrollbars appear with font size changes.*/
331 /* We have found that if it is visible, vertical scrollbars appear with font size changes.*/
332 overflow-y: hidden;
332 overflow-y: hidden;
333 overflow-x: auto; /* Changed from auto to remove scrollbar */
333 overflow-x: auto; /* Changed from auto to remove scrollbar */
334 }
334 }
335
335
336 /* CSS font colors for translated ANSI colors. */
336 /* CSS font colors for translated ANSI colors. */
337
337
338
338
339 .ansiblack {color: black;}
339 .ansiblack {color: black;}
340 .ansired {color: darkred;}
340 .ansired {color: darkred;}
341 .ansigreen {color: darkgreen;}
341 .ansigreen {color: darkgreen;}
342 .ansiyellow {color: brown;}
342 .ansiyellow {color: brown;}
343 .ansiblue {color: darkblue;}
343 .ansiblue {color: darkblue;}
344 .ansipurple {color: darkviolet;}
344 .ansipurple {color: darkviolet;}
345 .ansicyan {color: steelblue;}
345 .ansicyan {color: steelblue;}
346 .ansigrey {color: grey;}
346 .ansigrey {color: grey;}
347 .ansibold {font-weight: bold;}
347 .ansibold {font-weight: bold;}
348
348
349 .completions , .tooltip{
349 .completions , .tooltip{
350 position: absolute;
350 position: absolute;
351 z-index: 10;
351 z-index: 10;
352 overflow: auto;
352 overflow: auto;
353 border: 1px solid black;
353 border: 1px solid black;
354 }
354 }
355
355
356 .completions select {
356 .completions select {
357 background: white;
357 background: white;
358 outline: none;
358 outline: none;
359 border: none;
359 border: none;
360 padding: 0px;
360 padding: 0px;
361 margin: 0px;
361 margin: 0px;
362 font-family: monospace;
362 font-family: monospace;
363 }
363 }
364
364
365 @-moz-keyframes fadeIn {
365 @-moz-keyframes fadeIn {
366 from {opacity:0;}
366 from {opacity:0;}
367 to {opacity:1;}
367 to {opacity:1;}
368 }
368 }
369
369
370 @-webkit-keyframes fadeIn {
370 @-webkit-keyframes fadeIn {
371 from {opacity:0;}
371 from {opacity:0;}
372 to {opacity:1;}
372 to {opacity:1;}
373 }
373 }
374
374
375 @keyframes fadeIn {
375 @keyframes fadeIn {
376 from {opacity:0;}
376 from {opacity:0;}
377 to {opacity:1;}
377 to {opacity:1;}
378 }
378 }
379
379
380 /*"close" "expand" and "Open in pager button" of
380 /*"close" "expand" and "Open in pager button" of
381 /* the tooltip*/
381 /* the tooltip*/
382 .tooltip a{
382 .tooltip a{
383 float:right;
383 float:right;
384 }
384 }
385
385
386 /*properties of tooltip after "expand"*/
386 /*properties of tooltip after "expand"*/
387 .bigtooltip{
387 .bigtooltip{
388 height:30%;
388 height:30%;
389 }
389 }
390
390
391 /*properties of tooltip before "expand"*/
391 /*properties of tooltip before "expand"*/
392 .smalltooltip{
392 .smalltooltip{
393 text-overflow: ellipsis;
393 text-overflow: ellipsis;
394 overflow: hidden;
394 overflow: hidden;
395 height:15%;
395 height:15%;
396 }
396 }
397
397
398 .tooltip{
398 .tooltip{
399 /*transition when "expand"ing tooltip */
399 /*transition when "expand"ing tooltip */
400 -webkit-transition-property: height;
400 -webkit-transition-property: height;
401 -webkit-transition-duration: 1s;
401 -webkit-transition-duration: 1s;
402 -moz-transition-property: height;
402 -moz-transition-property: height;
403 -moz-transition-duration: 1s;
403 -moz-transition-duration: 1s;
404 transition-property: height;
404 transition-property: height;
405 transition-duration: 1s;
405 transition-duration: 1s;
406 max-width:700px;
406 max-width:700px;
407 border-radius: 0px 10px 10px 10px;
407 border-radius: 0px 10px 10px 10px;
408 box-shadow: 3px 3px 5px #999;
408 box-shadow: 3px 3px 5px #999;
409 /*fade-in animation when inserted*/
409 /*fade-in animation when inserted*/
410 -webkit-animation: fadeIn 200ms;
410 -webkit-animation: fadeIn 200ms;
411 -moz-animation: fadeIn 200ms;
411 -moz-animation: fadeIn 200ms;
412 animation: fadeIn 200ms;
412 animation: fadeIn 200ms;
413 vertical-align: middle;
413 vertical-align: middle;
414 background: #FDFDD8;
414 background: #FDFDD8;
415 outline: none;
415 outline: none;
416 padding: 3px;
416 padding: 3px;
417 margin: 0px;
417 margin: 0px;
418 font-family: monospace;
418 font-family: monospace;
419 min-height:50px;
419 min-height:50px;
420 }
420 }
421
421
422 /*fixed part of the completion*/
423 .completions p b{
424 font-weight:bold;
425 }
426
422 .completions p{
427 .completions p{
423 background: #DDF;
428 background: #DDF;
424 /*outline: none;
429 /*outline: none;
425 padding: 0px;*/
430 padding: 0px;*/
426 border-bottom: black solid 1px;
431 border-bottom: black solid 1px;
427 padding: 1px;
432 padding: 1px;
428 font-family: monospace;
433 font-family: monospace;
429 }
434 }
430
435
431 pre.dialog {
436 pre.dialog {
432 background-color: #f7f7f7;
437 background-color: #f7f7f7;
433 border: 1px solid #ddd;
438 border: 1px solid #ddd;
434 border-radius: 3px;
439 border-radius: 3px;
435 padding: 0.4em;
440 padding: 0.4em;
436 padding-left: 2em;
441 padding-left: 2em;
437 }
442 }
438
443
439 p.dialog{
444 p.dialog{
440 padding : 0.2em;
445 padding : 0.2em;
441 }
446 }
442
447
443 @media print {
448 @media print {
444 body { overflow: visible !important; }
449 body { overflow: visible !important; }
445 .ui-widget-content { border: 0px; }
450 .ui-widget-content { border: 0px; }
446 }
451 }
447
452
448 .shortcut_key {
453 .shortcut_key {
449 display: inline-block;
454 display: inline-block;
450 width: 13ex;
455 width: 13ex;
451 text-align: right;
456 text-align: right;
452 font-family: monospace;
457 font-family: monospace;
453 }
458 }
454
459
455 .shortcut_descr {
460 .shortcut_descr {
456 }
461 }
457
462
458 /* Word-wrap output correctly. This is the CSS3 spelling, though Firefox seems
463 /* Word-wrap output correctly. This is the CSS3 spelling, though Firefox seems
459 to not honor it correctly. Webkit browsers (Chrome, rekonq, Safari) do.
464 to not honor it correctly. Webkit browsers (Chrome, rekonq, Safari) do.
460 */
465 */
461 pre, code, kbd, samp { white-space: pre-wrap; }
466 pre, code, kbd, samp { white-space: pre-wrap; }
@@ -1,819 +1,827 b''
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008-2011 The IPython Development Team
2 // Copyright (C) 2008-2011 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // CodeCell
9 // CodeCell
10 //============================================================================
10 //============================================================================
11
11
12 var IPython = (function (IPython) {
12 var IPython = (function (IPython) {
13
13
14 var utils = IPython.utils;
14 var utils = IPython.utils;
15
15
16 var CodeCell = function (notebook) {
16 var CodeCell = function (notebook) {
17 this.code_mirror = null;
17 this.code_mirror = null;
18 this.input_prompt_number = ' ';
18 this.input_prompt_number = ' ';
19 this.is_completing = false;
19 this.is_completing = false;
20 this.completion_cursor = null;
20 this.completion_cursor = null;
21 this.outputs = [];
21 this.outputs = [];
22 this.collapsed = false;
22 this.collapsed = false;
23 this.tooltip_timeout = null;
23 this.tooltip_timeout = null;
24 IPython.Cell.apply(this, arguments);
24 IPython.Cell.apply(this, arguments);
25 };
25 };
26
26
27
27
28 CodeCell.prototype = new IPython.Cell();
28 CodeCell.prototype = new IPython.Cell();
29
29
30
30
31 CodeCell.prototype.create_element = function () {
31 CodeCell.prototype.create_element = function () {
32 var cell = $('<div></div>').addClass('cell border-box-sizing code_cell vbox');
32 var cell = $('<div></div>').addClass('cell border-box-sizing code_cell vbox');
33 cell.attr('tabindex','2');
33 cell.attr('tabindex','2');
34 var input = $('<div></div>').addClass('input hbox');
34 var input = $('<div></div>').addClass('input hbox');
35 input.append($('<div/>').addClass('prompt input_prompt'));
35 input.append($('<div/>').addClass('prompt input_prompt'));
36 var input_area = $('<div/>').addClass('input_area box-flex1');
36 var input_area = $('<div/>').addClass('input_area box-flex1');
37 this.code_mirror = CodeMirror(input_area.get(0), {
37 this.code_mirror = CodeMirror(input_area.get(0), {
38 indentUnit : 4,
38 indentUnit : 4,
39 mode: 'python',
39 mode: 'python',
40 theme: 'ipython',
40 theme: 'ipython',
41 readOnly: this.read_only,
41 readOnly: this.read_only,
42 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
42 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
43 });
43 });
44 input.append(input_area);
44 input.append(input_area);
45 var output = $('<div></div>').addClass('output vbox');
45 var output = $('<div></div>').addClass('output vbox');
46 cell.append(input).append(output);
46 cell.append(input).append(output);
47 this.element = cell;
47 this.element = cell;
48 this.collapse();
48 this.collapse();
49 };
49 };
50
50
51 //TODO, try to diminish the number of parameters.
51 //TODO, try to diminish the number of parameters.
52 CodeCell.prototype.request_tooltip_after_time = function (pre_cursor,time){
52 CodeCell.prototype.request_tooltip_after_time = function (pre_cursor,time){
53 var that = this;
53 var that = this;
54 if (pre_cursor === "" || pre_cursor === "(" ) {
54 if (pre_cursor === "" || pre_cursor === "(" ) {
55 // don't do anything if line beggin with '(' or is empty
55 // don't do anything if line beggin with '(' or is empty
56 } else {
56 } else {
57 // Will set a timer to request tooltip in `time`
57 // Will set a timer to request tooltip in `time`
58 that.tooltip_timeout = setTimeout(function(){
58 that.tooltip_timeout = setTimeout(function(){
59 IPython.notebook.request_tool_tip(that, pre_cursor)
59 IPython.notebook.request_tool_tip(that, pre_cursor)
60 },time);
60 },time);
61 }
61 }
62 };
62 };
63
63
64 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
64 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
65 // This method gets called in CodeMirror's onKeyDown/onKeyPress
65 // This method gets called in CodeMirror's onKeyDown/onKeyPress
66 // handlers and is used to provide custom key handling. Its return
66 // handlers and is used to provide custom key handling. Its return
67 // value is used to determine if CodeMirror should ignore the event:
67 // value is used to determine if CodeMirror should ignore the event:
68 // true = ignore, false = don't ignore.
68 // true = ignore, false = don't ignore.
69
69
70 // note that we are comparing and setting the time to wait at each key press.
70 // note that we are comparing and setting the time to wait at each key press.
71 // a better wqy might be to generate a new function on each time change and
71 // a better wqy might be to generate a new function on each time change and
72 // assign it to CodeCell.prototype.request_tooltip_after_time
72 // assign it to CodeCell.prototype.request_tooltip_after_time
73 tooltip_wait_time = this.notebook.time_before_tooltip;
73 tooltip_wait_time = this.notebook.time_before_tooltip;
74 tooltip_on_tab = this.notebook.tooltip_on_tab;
74 tooltip_on_tab = this.notebook.tooltip_on_tab;
75 var that = this;
75 var that = this;
76 // whatever key is pressed, first, cancel the tooltip request before
76 // whatever key is pressed, first, cancel the tooltip request before
77 // they are sent, and remove tooltip if any
77 // they are sent, and remove tooltip if any
78 if(event.type === 'keydown' ){
78 if(event.type === 'keydown' ){
79 that.remove_and_cancel_tooltip();
79 that.remove_and_cancel_tooltip();
80 }
80 }
81
81
82 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
82 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
83 // Always ignore shift-enter in CodeMirror as we handle it.
83 // Always ignore shift-enter in CodeMirror as we handle it.
84 return true;
84 return true;
85 }else if (event.which === 40 && event.type === 'keypress' && tooltip_wait_time >= 0) {
85 }else if (event.which === 40 && event.type === 'keypress' && tooltip_wait_time >= 0) {
86 // triger aon keypress (!) otherwise inconsistent event.which depending on plateform
86 // triger aon keypress (!) otherwise inconsistent event.which depending on plateform
87 // browser and keyboard layout !
87 // browser and keyboard layout !
88 // Pressing '(' , request tooltip, don't forget to reappend it
88 // Pressing '(' , request tooltip, don't forget to reappend it
89 var cursor = editor.getCursor();
89 var cursor = editor.getCursor();
90 var pre_cursor = editor.getRange({line:cursor.line,ch:0},cursor).trim()+'(';
90 var pre_cursor = editor.getRange({line:cursor.line,ch:0},cursor).trim()+'(';
91 that.request_tooltip_after_time(pre_cursor,tooltip_wait_time);
91 that.request_tooltip_after_time(pre_cursor,tooltip_wait_time);
92 } else if (event.keyCode === 9 && event.type == 'keydown') {
92 } else if (event.keyCode === 9 && event.type == 'keydown') {
93 // Tab completion.
93 // Tab completion.
94 var cur = editor.getCursor();
94 var cur = editor.getCursor();
95 //Do not trim here because of tooltip
95 //Do not trim here because of tooltip
96 var pre_cursor = editor.getRange({line:cur.line,ch:0},cur);
96 var pre_cursor = editor.getRange({line:cur.line,ch:0},cur);
97 if (pre_cursor.trim() === "") {
97 if (pre_cursor.trim() === "") {
98 // Don't autocomplete if the part of the line before the cursor
98 // Don't autocomplete if the part of the line before the cursor
99 // is empty. In this case, let CodeMirror handle indentation.
99 // is empty. In this case, let CodeMirror handle indentation.
100 return false;
100 return false;
101 } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && tooltip_on_tab ) {
101 } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && tooltip_on_tab ) {
102 that.request_tooltip_after_time(pre_cursor,0);
102 that.request_tooltip_after_time(pre_cursor,0);
103 } else {
103 } else {
104 pre_cursor.trim();
104 pre_cursor.trim();
105 // Autocomplete the current line.
105 // Autocomplete the current line.
106 event.stop();
106 event.stop();
107 var line = editor.getLine(cur.line);
107 var line = editor.getLine(cur.line);
108 this.is_completing = true;
108 this.is_completing = true;
109 this.completion_cursor = cur;
109 this.completion_cursor = cur;
110 IPython.notebook.complete_cell(this, line, cur.ch);
110 IPython.notebook.complete_cell(this, line, cur.ch);
111 return true;
111 return true;
112 }
112 }
113 } else if (event.keyCode === 8 && event.type == 'keydown') {
113 } else if (event.keyCode === 8 && event.type == 'keydown') {
114 // If backspace and the line ends with 4 spaces, remove them.
114 // If backspace and the line ends with 4 spaces, remove them.
115 var cur = editor.getCursor();
115 var cur = editor.getCursor();
116 var line = editor.getLine(cur.line);
116 var line = editor.getLine(cur.line);
117 var ending = line.slice(-4);
117 var ending = line.slice(-4);
118 if (ending === ' ') {
118 if (ending === ' ') {
119 editor.replaceRange('',
119 editor.replaceRange('',
120 {line: cur.line, ch: cur.ch-4},
120 {line: cur.line, ch: cur.ch-4},
121 {line: cur.line, ch: cur.ch}
121 {line: cur.line, ch: cur.ch}
122 );
122 );
123 event.stop();
123 event.stop();
124 return true;
124 return true;
125 } else {
125 } else {
126 return false;
126 return false;
127 }
127 }
128 } else if (event.keyCode === 76 && event.ctrlKey && event.shiftKey
128 } else if (event.keyCode === 76 && event.ctrlKey && event.shiftKey
129 && event.type == 'keydown') {
129 && event.type == 'keydown') {
130 // toggle line numbers with Ctrl-Shift-L
130 // toggle line numbers with Ctrl-Shift-L
131 this.toggle_line_numbers();
131 this.toggle_line_numbers();
132 }
132 }
133 else {
133 else {
134 // keypress/keyup also trigger on TAB press, and we don't want to
134 // keypress/keyup also trigger on TAB press, and we don't want to
135 // use those to disable tab completion.
135 // use those to disable tab completion.
136 if (this.is_completing && event.keyCode !== 9) {
136 if (this.is_completing && event.keyCode !== 9) {
137 var ed_cur = editor.getCursor();
137 var ed_cur = editor.getCursor();
138 var cc_cur = this.completion_cursor;
138 var cc_cur = this.completion_cursor;
139 if (ed_cur.line !== cc_cur.line || ed_cur.ch !== cc_cur.ch) {
139 if (ed_cur.line !== cc_cur.line || ed_cur.ch !== cc_cur.ch) {
140 this.is_completing = false;
140 this.is_completing = false;
141 this.completion_cursor = null;
141 this.completion_cursor = null;
142 }
142 }
143 }
143 }
144 return false;
144 return false;
145 };
145 };
146 return false;
146 return false;
147 };
147 };
148
148
149 CodeCell.prototype.remove_and_cancel_tooltip = function() {
149 CodeCell.prototype.remove_and_cancel_tooltip = function() {
150 // note that we don't handle closing directly inside the calltip
150 // note that we don't handle closing directly inside the calltip
151 // as in the completer, because it is not focusable, so won't
151 // as in the completer, because it is not focusable, so won't
152 // get the event.
152 // get the event.
153 if (this.tooltip_timeout != null){
153 if (this.tooltip_timeout != null){
154 clearTimeout(this.tooltip_timeout);
154 clearTimeout(this.tooltip_timeout);
155 $('#tooltip').remove();
155 $('#tooltip').remove();
156 this.tooltip_timeout = null;
156 this.tooltip_timeout = null;
157 }
157 }
158 }
158 }
159
159
160 CodeCell.prototype.finish_tooltip = function (reply) {
160 CodeCell.prototype.finish_tooltip = function (reply) {
161 defstring=reply.definition;
161 defstring=reply.definition;
162 docstring=reply.docstring;
162 docstring=reply.docstring;
163 if(docstring == null){docstring="<empty docstring>"};
163 if(docstring == null){docstring="<empty docstring>"};
164 name=reply.name;
164 name=reply.name;
165
165
166 var that = this;
166 var that = this;
167 var tooltip = $('<div/>').attr('id', 'tooltip').addClass('tooltip');
167 var tooltip = $('<div/>').attr('id', 'tooltip').addClass('tooltip');
168 // remove to have the tooltip not Limited in X and Y
168 // remove to have the tooltip not Limited in X and Y
169 tooltip.addClass('smalltooltip');
169 tooltip.addClass('smalltooltip');
170 var pre=$('<pre/>').html(utils.fixConsole(docstring));
170 var pre=$('<pre/>').html(utils.fixConsole(docstring));
171 var expandlink=$('<a/>').attr('href',"#");
171 var expandlink=$('<a/>').attr('href',"#");
172 expandlink.addClass("ui-corner-all"); //rounded corner
172 expandlink.addClass("ui-corner-all"); //rounded corner
173 expandlink.attr('role',"button");
173 expandlink.attr('role',"button");
174 //expandlink.addClass('ui-button');
174 //expandlink.addClass('ui-button');
175 //expandlink.addClass('ui-state-default');
175 //expandlink.addClass('ui-state-default');
176 var expandspan=$('<span/>').text('Expand');
176 var expandspan=$('<span/>').text('Expand');
177 expandspan.addClass('ui-icon');
177 expandspan.addClass('ui-icon');
178 expandspan.addClass('ui-icon-plus');
178 expandspan.addClass('ui-icon-plus');
179 expandlink.append(expandspan);
179 expandlink.append(expandspan);
180 expandlink.attr('id','expanbutton');
180 expandlink.attr('id','expanbutton');
181 expandlink.click(function(){
181 expandlink.click(function(){
182 tooltip.removeClass('smalltooltip');
182 tooltip.removeClass('smalltooltip');
183 tooltip.addClass('bigtooltip');
183 tooltip.addClass('bigtooltip');
184 $('#expanbutton').remove();
184 $('#expanbutton').remove();
185 setTimeout(function(){that.code_mirror.focus();}, 50);
185 setTimeout(function(){that.code_mirror.focus();}, 50);
186 });
186 });
187 var morelink=$('<a/>').attr('href',"#");
187 var morelink=$('<a/>').attr('href',"#");
188 morelink.attr('role',"button");
188 morelink.attr('role',"button");
189 morelink.addClass('ui-button');
189 morelink.addClass('ui-button');
190 //morelink.addClass("ui-corner-all"); //rounded corner
190 //morelink.addClass("ui-corner-all"); //rounded corner
191 //morelink.addClass('ui-state-default');
191 //morelink.addClass('ui-state-default');
192 var morespan=$('<span/>').text('Open in Pager');
192 var morespan=$('<span/>').text('Open in Pager');
193 morespan.addClass('ui-icon');
193 morespan.addClass('ui-icon');
194 morespan.addClass('ui-icon-arrowstop-l-n');
194 morespan.addClass('ui-icon-arrowstop-l-n');
195 morelink.append(morespan);
195 morelink.append(morespan);
196 morelink.click(function(){
196 morelink.click(function(){
197 var msg_id = IPython.notebook.kernel.execute(name+"?");
197 var msg_id = IPython.notebook.kernel.execute(name+"?");
198 IPython.notebook.msg_cell_map[msg_id] = IPython.notebook.selected_cell().cell_id;
198 IPython.notebook.msg_cell_map[msg_id] = IPython.notebook.selected_cell().cell_id;
199 that.remove_and_cancel_tooltip();
199 that.remove_and_cancel_tooltip();
200 setTimeout(function(){that.code_mirror.focus();}, 50);
200 setTimeout(function(){that.code_mirror.focus();}, 50);
201 });
201 });
202
202
203 var closelink=$('<a/>').attr('href',"#");
203 var closelink=$('<a/>').attr('href',"#");
204 closelink.attr('role',"button");
204 closelink.attr('role',"button");
205 closelink.addClass('ui-button');
205 closelink.addClass('ui-button');
206 //closelink.addClass("ui-corner-all"); //rounded corner
206 //closelink.addClass("ui-corner-all"); //rounded corner
207 //closelink.adClass('ui-state-default'); // grey background and blue cross
207 //closelink.adClass('ui-state-default'); // grey background and blue cross
208 var closespan=$('<span/>').text('Close');
208 var closespan=$('<span/>').text('Close');
209 closespan.addClass('ui-icon');
209 closespan.addClass('ui-icon');
210 closespan.addClass('ui-icon-close');
210 closespan.addClass('ui-icon-close');
211 closelink.append(closespan);
211 closelink.append(closespan);
212 closelink.click(function(){
212 closelink.click(function(){
213 that.remove_and_cancel_tooltip();
213 that.remove_and_cancel_tooltip();
214 setTimeout(function(){that.code_mirror.focus();}, 50);
214 setTimeout(function(){that.code_mirror.focus();}, 50);
215 });
215 });
216 //construct the tooltip
216 //construct the tooltip
217 tooltip.append(closelink);
217 tooltip.append(closelink);
218 tooltip.append(expandlink);
218 tooltip.append(expandlink);
219 tooltip.append(morelink);
219 tooltip.append(morelink);
220 if(defstring){
220 if(defstring){
221 defstring_html = $('<pre/>').html(utils.fixConsole(defstring));
221 defstring_html = $('<pre/>').html(utils.fixConsole(defstring));
222 tooltip.append(defstring_html);
222 tooltip.append(defstring_html);
223 }
223 }
224 tooltip.append(pre);
224 tooltip.append(pre);
225 var pos = this.code_mirror.cursorCoords();
225 var pos = this.code_mirror.cursorCoords();
226 tooltip.css('left',pos.x+'px');
226 tooltip.css('left',pos.x+'px');
227 tooltip.css('top',pos.yBot+'px');
227 tooltip.css('top',pos.yBot+'px');
228 $('body').append(tooltip);
228 $('body').append(tooltip);
229
229
230 // issues with cross-closing if multiple tooltip in less than 5sec
230 // issues with cross-closing if multiple tooltip in less than 5sec
231 // keep it comented for now
231 // keep it comented for now
232 // setTimeout(that.remove_and_cancel_tooltip, 5000);
232 // setTimeout(that.remove_and_cancel_tooltip, 5000);
233 };
233 };
234
234
235 // As you type completer
235 // As you type completer
236 CodeCell.prototype.finish_completing = function (matched_text, matches) {
236 CodeCell.prototype.finish_completing = function (matched_text, matches) {
237 //return if not completing or nothing to complete
237 //return if not completing or nothing to complete
238 if (!this.is_completing || matches.length === 0) {return;}
238 if (!this.is_completing || matches.length === 0) {return;}
239
239
240 // for later readability
240 // for later readability
241 var key = { tab:9,
241 var key = { tab:9,
242 esc:27,
242 esc:27,
243 backspace:8,
243 backspace:8,
244 space:13,
244 space:32,
245 shift:16,
245 shift:16,
246 enter:32,
246 enter:13,
247 // _ is 95
247 // _ is 95
248 isCompSymbol : function (code)
248 isCompSymbol : function (code)
249 {
249 {
250 return (code > 64 && code <= 90)
250 return (code > 64 && code <= 90)
251 || (code >= 97 && code <= 122)
251 || (code >= 97 && code <= 122)
252 || (code == 95)
252 || (code == 95)
253 },
253 },
254 dismissAndAppend : function (code)
254 dismissAndAppend : function (code)
255 {
255 {
256 chararr = ['(',')','[',']','+','-','/','\\','.'];
256 chararr = ['(',')','[',']','+','-','/','\\','.',' '];
257 codearr = chararr.map(function(x){return x.charCodeAt(0)});
257 codearr = chararr.map(function(x){return x.charCodeAt(0)});
258 return jQuery.inArray(code, codearr) != -1;
258 return jQuery.inArray(code, codearr) != -1;
259 }
259 }
260
260
261 }
261 }
262
262
263 // smart completion, sort kwarg ending with '='
263 // smart completion, sort kwarg ending with '='
264 var newm = new Array();
264 var newm = new Array();
265 if(this.notebook.smart_completer)
265 if(this.notebook.smart_completer)
266 {
266 {
267 kwargs = new Array();
267 kwargs = new Array();
268 other = new Array();
268 other = new Array();
269 for(var i = 0 ; i<matches.length ; ++i){
269 for(var i = 0 ; i<matches.length ; ++i){
270 if(matches[i].substr(-1) === '='){
270 if(matches[i].substr(-1) === '='){
271 kwargs.push(matches[i]);
271 kwargs.push(matches[i]);
272 }else{other.push(matches[i]);}
272 }else{other.push(matches[i]);}
273 }
273 }
274 newm = kwargs.concat(other);
274 newm = kwargs.concat(other);
275 matches = newm;
275 matches = newm;
276 }
276 }
277 // end sort kwargs
277 // end sort kwargs
278
278
279 // give common prefix of a array of string
279 // give common prefix of a array of string
280 function sharedStart(A){
280 function sharedStart(A){
281 if(A.length > 1 ){
281 if(A.length > 1 ){
282 var tem1, tem2, s, A = A.slice(0).sort();
282 var tem1, tem2, s, A = A.slice(0).sort();
283 tem1 = A[0];
283 tem1 = A[0];
284 s = tem1.length;
284 s = tem1.length;
285 tem2 = A.pop();
285 tem2 = A.pop();
286 while(s && tem2.indexOf(tem1) == -1){
286 while(s && tem2.indexOf(tem1) == -1){
287 tem1 = tem1.substring(0, --s);
287 tem1 = tem1.substring(0, --s);
288 }
288 }
289 return tem1;
289 return tem1;
290 }
290 }
291 return "";
291 return "";
292 }
292 }
293
293
294
294
295 //try to check if the user is typing tab at least twice after a word
295 //try to check if the user is typing tab at least twice after a word
296 // and completion is "done"
296 // and completion is "done"
297 fallback_on_tooltip_after = 2
297 fallback_on_tooltip_after = 2
298 if(matches.length == 1 && matched_text === matches[0])
298 if(matches.length == 1 && matched_text === matches[0])
299 {
299 {
300 if(this.npressed >fallback_on_tooltip_after && this.prevmatch==matched_text)
300 if(this.npressed >fallback_on_tooltip_after && this.prevmatch==matched_text)
301 {
301 {
302 console.log('Ok, you really want to complete after pressing tab '+this.npressed+' times !');
302 console.log('Ok, you really want to complete after pressing tab '+this.npressed+' times !');
303 console.log('You should understand that there is no (more) completion for that !');
303 console.log('You should understand that there is no (more) completion for that !');
304 console.log("I'll show you the tooltip, will you stop bothering me ?");
304 console.log("I'll show you the tooltip, will you stop bothering me ?");
305 this.request_tooltip_after_time(matched_text+'(',0);
305 this.request_tooltip_after_time(matched_text+'(',0);
306 return;
306 return;
307 }
307 }
308 this.prevmatch = matched_text
308 this.prevmatch = matched_text
309 this.npressed = this.npressed+1;
309 this.npressed = this.npressed+1;
310 }
310 }
311 else
311 else
312 {
312 {
313 this.prevmatch = "";
313 this.prevmatch = "";
314 this.npressed = 0;
314 this.npressed = 0;
315 }
315 }
316 // end fallback on tooltip
316 // end fallback on tooltip
317 //==================================
317 //==================================
318 // Real completion logic start here
318 // Real completion logic start here
319 var that = this;
319 var that = this;
320 var cur = this.completion_cursor;
320 var cur = this.completion_cursor;
321 var done = false;
321 var done = false;
322
322
323 // call to dismmiss the completer
323 // call to dismmiss the completer
324 var close = function () {
324 var close = function () {
325 if (done) return;
325 if (done) return;
326 done = true;
326 done = true;
327 if (complete != undefined)
327 if (complete != undefined)
328 {complete.remove();}
328 {complete.remove();}
329 that.is_completing = false;
329 that.is_completing = false;
330 that.completion_cursor = null;
330 that.completion_cursor = null;
331 };
331 };
332
332
333 // insert the given text and exit the completer
333 // update codemirror with the typed text
334 var insert = function (selected_text, event) {
334 prev = matched_text
335 var update = function (inserted_text, event) {
335 that.code_mirror.replaceRange(
336 that.code_mirror.replaceRange(
336 selected_text,
337 inserted_text,
337 {line: cur.line, ch: (cur.ch-matched_text.length)},
338 {line: cur.line, ch: (cur.ch-matched_text.length)},
338 {line: cur.line, ch: cur.ch}
339 {line: cur.line, ch: (cur.ch+prev.length-matched_text.length)}
339 );
340 );
341 prev = inserted_text
340 if(event != null){
342 if(event != null){
341 event.stopPropagation();
343 event.stopPropagation();
342 event.preventDefault();
344 event.preventDefault();
343 }
345 }
346 };
347 // insert the given text and exit the completer
348 var insert = function (selected_text, event) {
349 update(selected_text)
344 close();
350 close();
345 setTimeout(function(){that.code_mirror.focus();}, 50);
351 setTimeout(function(){that.code_mirror.focus();}, 50);
346 };
352 };
347
353
348 // insert the curent highlited selection and exit
354 // insert the curent highlited selection and exit
349 var pick = function () {
355 var pick = function () {
350 insert(select.val()[0],null);
356 insert(select.val()[0],null);
351 };
357 };
352
358
353
359
354 // Define function to clear the completer, refill it with the new
360 // Define function to clear the completer, refill it with the new
355 // matches, update the pseuso typing field. autopick insert match if
361 // matches, update the pseuso typing field. autopick insert match if
356 // only one left, in no matches (anymore) dismiss itself by pasting
362 // only one left, in no matches (anymore) dismiss itself by pasting
357 // what the user have typed until then
363 // what the user have typed until then
358 var complete_with = function(matches,typed_text,autopick,event)
364 var complete_with = function(matches,typed_text,autopick,event)
359 {
365 {
360 // If autopick an only one match, past.
366 // If autopick an only one match, past.
361 // Used to 'pick' when pressing tab
367 // Used to 'pick' when pressing tab
362 if (matches.length < 1) {
368 if (matches.length < 1) {
363 insert(typed_text,event);
369 insert(typed_text,event);
364 if(event != null){
370 if(event != null){
365 event.stopPropagation();
371 event.stopPropagation();
366 event.preventDefault();
372 event.preventDefault();
367 }
373 }
368 } else if (autopick && matches.length == 1) {
374 } else if (autopick && matches.length == 1) {
369 insert(matches[0],event);
375 insert(matches[0],event);
370 if(event != null){
376 if(event != null){
371 event.stopPropagation();
377 event.stopPropagation();
372 event.preventDefault();
378 event.preventDefault();
373 }
379 }
374 }
380 }
375 //clear the previous completion if any
381 //clear the previous completion if any
382 update(typed_text,event);
376 complete.children().children().remove();
383 complete.children().children().remove();
377 $('#asyoutype').text(typed_text);
384 $('#asyoutype').html("<b>"+matched_text+"</b>"+typed_text.substr(matched_text.length));
378 select = $('#asyoutypeselect');
385 select = $('#asyoutypeselect');
379 for (var i = 0; i<matches.length; ++i) {
386 for (var i = 0; i<matches.length; ++i) {
380 select.append($('<option/>').html(matches[i]));
387 select.append($('<option/>').html(matches[i]));
381 }
388 }
382 select.children().first().attr('selected','true');
389 select.children().first().attr('selected','true');
383 }
390 }
384
391
385 // create html for completer
392 // create html for completer
386 var complete = $('<div/>').addClass('completions');
393 var complete = $('<div/>').addClass('completions');
387 complete.attr('id','complete');
394 complete.attr('id','complete');
388 complete.append($('<p/>').attr('id', 'asyoutype').html(matched_text));//pseudo input field
395 complete.append($('<p/>').attr('id', 'asyoutype').html('<b>fixed part</b>user part'));//pseudo input field
389
396
390 var select = $('<select/>').attr('multiple','true');
397 var select = $('<select/>').attr('multiple','true');
391 select.attr('id', 'asyoutypeselect')
398 select.attr('id', 'asyoutypeselect')
392 select.attr('size',Math.min(10,matches.length));
399 select.attr('size',Math.min(10,matches.length));
393 var pos = this.code_mirror.cursorCoords();
400 var pos = this.code_mirror.cursorCoords();
394
401
395 // TODO: I propose to remove enough horizontal pixel
402 // TODO: I propose to remove enough horizontal pixel
396 // to align the text later
403 // to align the text later
397 complete.css('left',pos.x+'px');
404 complete.css('left',pos.x+'px');
398 complete.css('top',pos.yBot+'px');
405 complete.css('top',pos.yBot+'px');
399 complete.append(select);
406 complete.append(select);
400
407
401 $('body').append(complete);
408 $('body').append(complete);
402
409
403 // So a first actual completion. see if all the completion start wit
410 // So a first actual completion. see if all the completion start wit
404 // the same letter and complete if necessary
411 // the same letter and complete if necessary
405 fastForward = sharedStart(matches)
412 fastForward = sharedStart(matches)
406 typed_characters = fastForward.substr(matched_text.length);
413 typed_characters = fastForward.substr(matched_text.length);
407 complete_with(matches,matched_text+typed_characters,true,null);
414 complete_with(matches,matched_text+typed_characters,true,null);
408 filterd = matches;
415 filterd = matches;
409 // Give focus to select, and make it filter the match as the user type
416 // Give focus to select, and make it filter the match as the user type
410 // by filtering the previous matches. Called by .keypress and .keydown
417 // by filtering the previous matches. Called by .keypress and .keydown
411 var downandpress = function (event,press_or_down) {
418 var downandpress = function (event,press_or_down) {
412 var code = event.which;
419 var code = event.which;
413 var autopick = false; // auto 'pick' if only one match
420 var autopick = false; // auto 'pick' if only one match
414 if (press_or_down === 0){
421 if (press_or_down === 0){
415 press = true; down = false; //Are we called from keypress or keydown
422 press = true; down = false; //Are we called from keypress or keydown
416 } else if (press_or_down == 1){
423 } else if (press_or_down == 1){
417 press = false; down = true;
424 press = false; down = true;
418 }
425 }
419 if (code === key.shift) {
426 if (code === key.shift) {
420 // nothing on Shift
427 // nothing on Shift
421 return;
428 return;
422 }
429 }
423 if (key.dismissAndAppend(code) && press) {
430 if (key.dismissAndAppend(code) && press) {
424 var newchar = String.fromCharCode(code);
431 var newchar = String.fromCharCode(code);
425 typed_characters = typed_characters+newchar;
432 typed_characters = typed_characters+newchar;
426 insert(matched_text+typed_characters,event);
433 insert(matched_text+typed_characters,event);
427 return
434 return
428 }
435 }
429 if (code === key.space || code === key.enter) {
436 if (code === key.enter) {
430 // Pressing SPACE or ENTER will cause a pick
437 // Pressing ENTER will cause a pick
431 event.stopPropagation();
438 event.stopPropagation();
432 event.preventDefault();
439 event.preventDefault();
433 pick();
440 pick();
434 } else if (code === 38 || code === 40) {
441 } else if (code === 38 || code === 40) {
435 // We don't want the document keydown handler to handle UP/DOWN,
442 // We don't want the document keydown handler to handle UP/DOWN,
436 // but we want the default action.
443 // but we want the default action.
437 event.stopPropagation();
444 event.stopPropagation();
438 } else if ( (code == key.backspace)||(code == key.tab && down) || press || key.isCompSymbol(code)){
445 } else if ( (code == key.backspace)||(code == key.tab && down) || press || key.isCompSymbol(code)){
439 if( key.isCompSymbol(code) && press)
446 if( key.isCompSymbol(code) && press)
440 {
447 {
441 var newchar = String.fromCharCode(code);
448 var newchar = String.fromCharCode(code);
442 typed_characters = typed_characters+newchar;
449 typed_characters = typed_characters+newchar;
443 } else if (code == key.tab) {
450 } else if (code == key.tab) {
444 fastForward = sharedStart(filterd)
451 fastForward = sharedStart(filterd)
445 ffsub = fastForward.substr(matched_text.length+typed_characters.length);
452 ffsub = fastForward.substr(matched_text.length+typed_characters.length);
446 typed_characters = typed_characters+ffsub;
453 typed_characters = typed_characters+ffsub;
447 autopick = true;
454 autopick = true;
448 event.stopPropagation();
449 event.preventDefault();
450 } else if (code == key.backspace && down) {
455 } else if (code == key.backspace && down) {
451 // cancel if user have erase everything, otherwise decrease
456 // cancel if user have erase everything, otherwise decrease
452 // what we filter with
457 // what we filter with
458 event.preventDefault();
453 if (typed_characters.length <= 0)
459 if (typed_characters.length <= 0)
454 {
460 {
455 insert(matched_text,event)
461 insert(matched_text,event)
456 return
462 return
457 }
463 }
458 typed_characters = typed_characters.substr(0,typed_characters.length-1);
464 typed_characters = typed_characters.substr(0,typed_characters.length-1);
459 } else if (press && code != key.backspace && code != key.tab && code != 0){
465 } else if (press && code != key.backspace && code != key.tab && code != 0){
460 insert(matched_text+typed_characters,event);
466 insert(matched_text+typed_characters,event);
461 return
467 return
462 } else {
468 } else {
463 return
469 return
464 }
470 }
465 re = new RegExp("^"+"\%?"+matched_text+typed_characters,"");
471 re = new RegExp("^"+"\%?"+matched_text+typed_characters,"");
466 filterd = matches.filter(function(x){return re.test(x)});
472 filterd = matches.filter(function(x){return re.test(x)});
467 complete_with(filterd,matched_text+typed_characters,autopick,event);
473 complete_with(filterd,matched_text+typed_characters,autopick,event);
468 } else if( press || code == key.esc){ // abort only on .keypress or esc
474 } else if( code == key.esc) {
475 // dismiss the completer and go back to before invoking it
476 insert(matched_text,event);
477 } else if( press ){ // abort only on .keypress or esc
469 // abort with what the user have pressed until now
478 // abort with what the user have pressed until now
470 console.log('aborting with keycode : '+code+' is down :'+down);
479 console.log('aborting with keycode : '+code+' is down :'+down);
471 insert(matched_text+typed_characters,event);
472 }
480 }
473 }
481 }
474 select.keydown(function (event) {
482 select.keydown(function (event) {
475 downandpress(event,1)
483 downandpress(event,1)
476 });
484 });
477 select.keypress(function (event) {
485 select.keypress(function (event) {
478 downandpress(event,0)
486 downandpress(event,0)
479 });
487 });
480 // Double click also causes a pick.
488 // Double click also causes a pick.
481 // and bind the last actions.
489 // and bind the last actions.
482 select.dblclick(pick);
490 select.dblclick(pick);
483 select.blur(close);
491 select.blur(close);
484 select.focus();
492 select.focus();
485 };
493 };
486
494
487 CodeCell.prototype.toggle_line_numbers = function () {
495 CodeCell.prototype.toggle_line_numbers = function () {
488 if (this.code_mirror.getOption('lineNumbers') == false) {
496 if (this.code_mirror.getOption('lineNumbers') == false) {
489 this.code_mirror.setOption('lineNumbers', true);
497 this.code_mirror.setOption('lineNumbers', true);
490 } else {
498 } else {
491 this.code_mirror.setOption('lineNumbers', false);
499 this.code_mirror.setOption('lineNumbers', false);
492 }
500 }
493 this.code_mirror.refresh();
501 this.code_mirror.refresh();
494 };
502 };
495
503
496 CodeCell.prototype.select = function () {
504 CodeCell.prototype.select = function () {
497 IPython.Cell.prototype.select.apply(this);
505 IPython.Cell.prototype.select.apply(this);
498 // Todo: this dance is needed because as of CodeMirror 2.12, focus is
506 // Todo: this dance is needed because as of CodeMirror 2.12, focus is
499 // not causing the cursor to blink if the editor is empty initially.
507 // not causing the cursor to blink if the editor is empty initially.
500 // While this seems to fix the issue, this should be fixed
508 // While this seems to fix the issue, this should be fixed
501 // in CodeMirror proper.
509 // in CodeMirror proper.
502 var s = this.code_mirror.getValue();
510 var s = this.code_mirror.getValue();
503 this.code_mirror.focus();
511 this.code_mirror.focus();
504 if (s === '') this.code_mirror.setValue('');
512 if (s === '') this.code_mirror.setValue('');
505 };
513 };
506
514
507
515
508 CodeCell.prototype.select_all = function () {
516 CodeCell.prototype.select_all = function () {
509 var start = {line: 0, ch: 0};
517 var start = {line: 0, ch: 0};
510 var nlines = this.code_mirror.lineCount();
518 var nlines = this.code_mirror.lineCount();
511 var last_line = this.code_mirror.getLine(nlines-1);
519 var last_line = this.code_mirror.getLine(nlines-1);
512 var end = {line: nlines-1, ch: last_line.length};
520 var end = {line: nlines-1, ch: last_line.length};
513 this.code_mirror.setSelection(start, end);
521 this.code_mirror.setSelection(start, end);
514 };
522 };
515
523
516
524
517 CodeCell.prototype.append_output = function (json) {
525 CodeCell.prototype.append_output = function (json) {
518 this.expand();
526 this.expand();
519 if (json.output_type === 'pyout') {
527 if (json.output_type === 'pyout') {
520 this.append_pyout(json);
528 this.append_pyout(json);
521 } else if (json.output_type === 'pyerr') {
529 } else if (json.output_type === 'pyerr') {
522 this.append_pyerr(json);
530 this.append_pyerr(json);
523 } else if (json.output_type === 'display_data') {
531 } else if (json.output_type === 'display_data') {
524 this.append_display_data(json);
532 this.append_display_data(json);
525 } else if (json.output_type === 'stream') {
533 } else if (json.output_type === 'stream') {
526 this.append_stream(json);
534 this.append_stream(json);
527 };
535 };
528 this.outputs.push(json);
536 this.outputs.push(json);
529 };
537 };
530
538
531
539
532 CodeCell.prototype.create_output_area = function () {
540 CodeCell.prototype.create_output_area = function () {
533 var oa = $("<div/>").addClass("hbox output_area");
541 var oa = $("<div/>").addClass("hbox output_area");
534 oa.append($('<div/>').addClass('prompt'));
542 oa.append($('<div/>').addClass('prompt'));
535 return oa;
543 return oa;
536 };
544 };
537
545
538
546
539 CodeCell.prototype.append_pyout = function (json) {
547 CodeCell.prototype.append_pyout = function (json) {
540 n = json.prompt_number || ' ';
548 n = json.prompt_number || ' ';
541 var toinsert = this.create_output_area();
549 var toinsert = this.create_output_area();
542 toinsert.find('div.prompt').addClass('output_prompt').html('Out[' + n + ']:');
550 toinsert.find('div.prompt').addClass('output_prompt').html('Out[' + n + ']:');
543 this.append_mime_type(json, toinsert);
551 this.append_mime_type(json, toinsert);
544 this.element.find('div.output').append(toinsert);
552 this.element.find('div.output').append(toinsert);
545 // If we just output latex, typeset it.
553 // If we just output latex, typeset it.
546 if ((json.latex !== undefined) || (json.html !== undefined)) {
554 if ((json.latex !== undefined) || (json.html !== undefined)) {
547 this.typeset();
555 this.typeset();
548 };
556 };
549 };
557 };
550
558
551
559
552 CodeCell.prototype.append_pyerr = function (json) {
560 CodeCell.prototype.append_pyerr = function (json) {
553 var tb = json.traceback;
561 var tb = json.traceback;
554 if (tb !== undefined && tb.length > 0) {
562 if (tb !== undefined && tb.length > 0) {
555 var s = '';
563 var s = '';
556 var len = tb.length;
564 var len = tb.length;
557 for (var i=0; i<len; i++) {
565 for (var i=0; i<len; i++) {
558 s = s + tb[i] + '\n';
566 s = s + tb[i] + '\n';
559 }
567 }
560 s = s + '\n';
568 s = s + '\n';
561 var toinsert = this.create_output_area();
569 var toinsert = this.create_output_area();
562 this.append_text(s, toinsert);
570 this.append_text(s, toinsert);
563 this.element.find('div.output').append(toinsert);
571 this.element.find('div.output').append(toinsert);
564 };
572 };
565 };
573 };
566
574
567
575
568 CodeCell.prototype.append_stream = function (json) {
576 CodeCell.prototype.append_stream = function (json) {
569 // temporary fix: if stream undefined (json file written prior to this patch),
577 // temporary fix: if stream undefined (json file written prior to this patch),
570 // default to most likely stdout:
578 // default to most likely stdout:
571 if (json.stream == undefined){
579 if (json.stream == undefined){
572 json.stream = 'stdout';
580 json.stream = 'stdout';
573 }
581 }
574 var subclass = "output_"+json.stream;
582 var subclass = "output_"+json.stream;
575 if (this.outputs.length > 0){
583 if (this.outputs.length > 0){
576 // have at least one output to consider
584 // have at least one output to consider
577 var last = this.outputs[this.outputs.length-1];
585 var last = this.outputs[this.outputs.length-1];
578 if (last.output_type == 'stream' && json.stream == last.stream){
586 if (last.output_type == 'stream' && json.stream == last.stream){
579 // latest output was in the same stream,
587 // latest output was in the same stream,
580 // so append directly into its pre tag
588 // so append directly into its pre tag
581 this.element.find('div.'+subclass).last().find('pre').append(json.text);
589 this.element.find('div.'+subclass).last().find('pre').append(json.text);
582 return;
590 return;
583 }
591 }
584 }
592 }
585
593
586 // If we got here, attach a new div
594 // If we got here, attach a new div
587 var toinsert = this.create_output_area();
595 var toinsert = this.create_output_area();
588 this.append_text(json.text, toinsert, "output_stream "+subclass);
596 this.append_text(json.text, toinsert, "output_stream "+subclass);
589 this.element.find('div.output').append(toinsert);
597 this.element.find('div.output').append(toinsert);
590 };
598 };
591
599
592
600
593 CodeCell.prototype.append_display_data = function (json) {
601 CodeCell.prototype.append_display_data = function (json) {
594 var toinsert = this.create_output_area();
602 var toinsert = this.create_output_area();
595 this.append_mime_type(json, toinsert);
603 this.append_mime_type(json, toinsert);
596 this.element.find('div.output').append(toinsert);
604 this.element.find('div.output').append(toinsert);
597 // If we just output latex, typeset it.
605 // If we just output latex, typeset it.
598 if ( (json.latex !== undefined) || (json.html !== undefined) ) {
606 if ( (json.latex !== undefined) || (json.html !== undefined) ) {
599 this.typeset();
607 this.typeset();
600 };
608 };
601 };
609 };
602
610
603
611
604 CodeCell.prototype.append_mime_type = function (json, element) {
612 CodeCell.prototype.append_mime_type = function (json, element) {
605 if (json.html !== undefined) {
613 if (json.html !== undefined) {
606 this.append_html(json.html, element);
614 this.append_html(json.html, element);
607 } else if (json.latex !== undefined) {
615 } else if (json.latex !== undefined) {
608 this.append_latex(json.latex, element);
616 this.append_latex(json.latex, element);
609 } else if (json.svg !== undefined) {
617 } else if (json.svg !== undefined) {
610 this.append_svg(json.svg, element);
618 this.append_svg(json.svg, element);
611 } else if (json.png !== undefined) {
619 } else if (json.png !== undefined) {
612 this.append_png(json.png, element);
620 this.append_png(json.png, element);
613 } else if (json.jpeg !== undefined) {
621 } else if (json.jpeg !== undefined) {
614 this.append_jpeg(json.jpeg, element);
622 this.append_jpeg(json.jpeg, element);
615 } else if (json.text !== undefined) {
623 } else if (json.text !== undefined) {
616 this.append_text(json.text, element);
624 this.append_text(json.text, element);
617 };
625 };
618 };
626 };
619
627
620
628
621 CodeCell.prototype.append_html = function (html, element) {
629 CodeCell.prototype.append_html = function (html, element) {
622 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_html rendered_html");
630 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_html rendered_html");
623 toinsert.append(html);
631 toinsert.append(html);
624 element.append(toinsert);
632 element.append(toinsert);
625 };
633 };
626
634
627
635
628 CodeCell.prototype.append_text = function (data, element, extra_class) {
636 CodeCell.prototype.append_text = function (data, element, extra_class) {
629 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_text");
637 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_text");
630 if (extra_class){
638 if (extra_class){
631 toinsert.addClass(extra_class);
639 toinsert.addClass(extra_class);
632 }
640 }
633 toinsert.append($("<pre/>").html(data));
641 toinsert.append($("<pre/>").html(data));
634 element.append(toinsert);
642 element.append(toinsert);
635 };
643 };
636
644
637
645
638 CodeCell.prototype.append_svg = function (svg, element) {
646 CodeCell.prototype.append_svg = function (svg, element) {
639 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_svg");
647 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_svg");
640 toinsert.append(svg);
648 toinsert.append(svg);
641 element.append(toinsert);
649 element.append(toinsert);
642 };
650 };
643
651
644
652
645 CodeCell.prototype.append_png = function (png, element) {
653 CodeCell.prototype.append_png = function (png, element) {
646 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_png");
654 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_png");
647 toinsert.append($("<img/>").attr('src','data:image/png;base64,'+png));
655 toinsert.append($("<img/>").attr('src','data:image/png;base64,'+png));
648 element.append(toinsert);
656 element.append(toinsert);
649 };
657 };
650
658
651
659
652 CodeCell.prototype.append_jpeg = function (jpeg, element) {
660 CodeCell.prototype.append_jpeg = function (jpeg, element) {
653 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_jpeg");
661 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_jpeg");
654 toinsert.append($("<img/>").attr('src','data:image/jpeg;base64,'+jpeg));
662 toinsert.append($("<img/>").attr('src','data:image/jpeg;base64,'+jpeg));
655 element.append(toinsert);
663 element.append(toinsert);
656 };
664 };
657
665
658
666
659 CodeCell.prototype.append_latex = function (latex, element) {
667 CodeCell.prototype.append_latex = function (latex, element) {
660 // This method cannot do the typesetting because the latex first has to
668 // This method cannot do the typesetting because the latex first has to
661 // be on the page.
669 // be on the page.
662 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_latex");
670 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_latex");
663 toinsert.append(latex);
671 toinsert.append(latex);
664 element.append(toinsert);
672 element.append(toinsert);
665 };
673 };
666
674
667
675
668 CodeCell.prototype.clear_output = function (stdout, stderr, other) {
676 CodeCell.prototype.clear_output = function (stdout, stderr, other) {
669 var output_div = this.element.find("div.output");
677 var output_div = this.element.find("div.output");
670 if (stdout && stderr && other){
678 if (stdout && stderr && other){
671 // clear all, no need for logic
679 // clear all, no need for logic
672 output_div.html("");
680 output_div.html("");
673 this.outputs = [];
681 this.outputs = [];
674 return;
682 return;
675 }
683 }
676 // remove html output
684 // remove html output
677 // each output_subarea that has an identifying class is in an output_area
685 // each output_subarea that has an identifying class is in an output_area
678 // which is the element to be removed.
686 // which is the element to be removed.
679 if (stdout){
687 if (stdout){
680 output_div.find("div.output_stdout").parent().remove();
688 output_div.find("div.output_stdout").parent().remove();
681 }
689 }
682 if (stderr){
690 if (stderr){
683 output_div.find("div.output_stderr").parent().remove();
691 output_div.find("div.output_stderr").parent().remove();
684 }
692 }
685 if (other){
693 if (other){
686 output_div.find("div.output_subarea").not("div.output_stderr").not("div.output_stdout").parent().remove();
694 output_div.find("div.output_subarea").not("div.output_stderr").not("div.output_stdout").parent().remove();
687 }
695 }
688
696
689 // remove cleared outputs from JSON list:
697 // remove cleared outputs from JSON list:
690 for (var i = this.outputs.length - 1; i >= 0; i--){
698 for (var i = this.outputs.length - 1; i >= 0; i--){
691 var out = this.outputs[i];
699 var out = this.outputs[i];
692 var output_type = out.output_type;
700 var output_type = out.output_type;
693 if (output_type == "display_data" && other){
701 if (output_type == "display_data" && other){
694 this.outputs.splice(i,1);
702 this.outputs.splice(i,1);
695 }else if (output_type == "stream"){
703 }else if (output_type == "stream"){
696 if (stdout && out.stream == "stdout"){
704 if (stdout && out.stream == "stdout"){
697 this.outputs.splice(i,1);
705 this.outputs.splice(i,1);
698 }else if (stderr && out.stream == "stderr"){
706 }else if (stderr && out.stream == "stderr"){
699 this.outputs.splice(i,1);
707 this.outputs.splice(i,1);
700 }
708 }
701 }
709 }
702 }
710 }
703 };
711 };
704
712
705
713
706 CodeCell.prototype.clear_input = function () {
714 CodeCell.prototype.clear_input = function () {
707 this.code_mirror.setValue('');
715 this.code_mirror.setValue('');
708 };
716 };
709
717
710
718
711 CodeCell.prototype.collapse = function () {
719 CodeCell.prototype.collapse = function () {
712 if (!this.collapsed) {
720 if (!this.collapsed) {
713 this.element.find('div.output').hide();
721 this.element.find('div.output').hide();
714 this.collapsed = true;
722 this.collapsed = true;
715 };
723 };
716 };
724 };
717
725
718
726
719 CodeCell.prototype.expand = function () {
727 CodeCell.prototype.expand = function () {
720 if (this.collapsed) {
728 if (this.collapsed) {
721 this.element.find('div.output').show();
729 this.element.find('div.output').show();
722 this.collapsed = false;
730 this.collapsed = false;
723 };
731 };
724 };
732 };
725
733
726
734
727 CodeCell.prototype.toggle_output = function () {
735 CodeCell.prototype.toggle_output = function () {
728 if (this.collapsed) {
736 if (this.collapsed) {
729 this.expand();
737 this.expand();
730 } else {
738 } else {
731 this.collapse();
739 this.collapse();
732 };
740 };
733 };
741 };
734
742
735 CodeCell.prototype.set_input_prompt = function (number) {
743 CodeCell.prototype.set_input_prompt = function (number) {
736 var n = number || '&nbsp;';
744 var n = number || '&nbsp;';
737 this.input_prompt_number = n;
745 this.input_prompt_number = n;
738 this.element.find('div.input_prompt').html('In&nbsp;[' + n + ']:');
746 this.element.find('div.input_prompt').html('In&nbsp;[' + n + ']:');
739 };
747 };
740
748
741
749
742 CodeCell.prototype.get_code = function () {
750 CodeCell.prototype.get_code = function () {
743 return this.code_mirror.getValue();
751 return this.code_mirror.getValue();
744 };
752 };
745
753
746
754
747 CodeCell.prototype.set_code = function (code) {
755 CodeCell.prototype.set_code = function (code) {
748 return this.code_mirror.setValue(code);
756 return this.code_mirror.setValue(code);
749 };
757 };
750
758
751
759
752 CodeCell.prototype.at_top = function () {
760 CodeCell.prototype.at_top = function () {
753 var cursor = this.code_mirror.getCursor();
761 var cursor = this.code_mirror.getCursor();
754 if (cursor.line === 0) {
762 if (cursor.line === 0) {
755 return true;
763 return true;
756 } else {
764 } else {
757 return false;
765 return false;
758 }
766 }
759 };
767 };
760
768
761
769
762 CodeCell.prototype.at_bottom = function () {
770 CodeCell.prototype.at_bottom = function () {
763 var cursor = this.code_mirror.getCursor();
771 var cursor = this.code_mirror.getCursor();
764 if (cursor.line === (this.code_mirror.lineCount()-1)) {
772 if (cursor.line === (this.code_mirror.lineCount()-1)) {
765 return true;
773 return true;
766 } else {
774 } else {
767 return false;
775 return false;
768 }
776 }
769 };
777 };
770
778
771
779
772 CodeCell.prototype.fromJSON = function (data) {
780 CodeCell.prototype.fromJSON = function (data) {
773 console.log('Import from JSON:', data);
781 console.log('Import from JSON:', data);
774 if (data.cell_type === 'code') {
782 if (data.cell_type === 'code') {
775 if (data.input !== undefined) {
783 if (data.input !== undefined) {
776 this.set_code(data.input);
784 this.set_code(data.input);
777 }
785 }
778 if (data.prompt_number !== undefined) {
786 if (data.prompt_number !== undefined) {
779 this.set_input_prompt(data.prompt_number);
787 this.set_input_prompt(data.prompt_number);
780 } else {
788 } else {
781 this.set_input_prompt();
789 this.set_input_prompt();
782 };
790 };
783 var len = data.outputs.length;
791 var len = data.outputs.length;
784 for (var i=0; i<len; i++) {
792 for (var i=0; i<len; i++) {
785 this.append_output(data.outputs[i]);
793 this.append_output(data.outputs[i]);
786 };
794 };
787 if (data.collapsed !== undefined) {
795 if (data.collapsed !== undefined) {
788 if (data.collapsed) {
796 if (data.collapsed) {
789 this.collapse();
797 this.collapse();
790 };
798 };
791 };
799 };
792 };
800 };
793 };
801 };
794
802
795
803
796 CodeCell.prototype.toJSON = function () {
804 CodeCell.prototype.toJSON = function () {
797 var data = {};
805 var data = {};
798 data.input = this.get_code();
806 data.input = this.get_code();
799 data.cell_type = 'code';
807 data.cell_type = 'code';
800 if (this.input_prompt_number !== ' ') {
808 if (this.input_prompt_number !== ' ') {
801 data.prompt_number = this.input_prompt_number;
809 data.prompt_number = this.input_prompt_number;
802 };
810 };
803 var outputs = [];
811 var outputs = [];
804 var len = this.outputs.length;
812 var len = this.outputs.length;
805 for (var i=0; i<len; i++) {
813 for (var i=0; i<len; i++) {
806 outputs[i] = this.outputs[i];
814 outputs[i] = this.outputs[i];
807 };
815 };
808 data.outputs = outputs;
816 data.outputs = outputs;
809 data.language = 'python';
817 data.language = 'python';
810 data.collapsed = this.collapsed;
818 data.collapsed = this.collapsed;
811 // console.log('Export to JSON:',data);
819 // console.log('Export to JSON:',data);
812 return data;
820 return data;
813 };
821 };
814
822
815
823
816 IPython.CodeCell = CodeCell;
824 IPython.CodeCell = CodeCell;
817
825
818 return IPython;
826 return IPython;
819 }(IPython));
827 }(IPython));
General Comments 0
You need to be logged in to leave comments. Login now