##// END OF EJS Templates
fix firefox (windows) break line on empty prompt number
Bussonnier Matthias -
Show More
@@ -1,674 +1,674
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2008-2011 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // CodeCell
10 10 //============================================================================
11 11
12 12 var IPython = (function (IPython) {
13 13
14 14 var utils = IPython.utils;
15 15
16 16 var CodeCell = function (notebook) {
17 17 this.code_mirror = null;
18 this.input_prompt_number = ' ';
18 this.input_prompt_number = ' ';
19 19 this.is_completing = false;
20 20 this.completion_cursor = null;
21 21 this.outputs = [];
22 22 this.collapsed = false;
23 23 IPython.Cell.apply(this, arguments);
24 24 };
25 25
26 26
27 27 CodeCell.prototype = new IPython.Cell();
28 28
29 29
30 30 CodeCell.prototype.create_element = function () {
31 31 var cell = $('<div></div>').addClass('cell border-box-sizing code_cell vbox');
32 32 cell.attr('tabindex','2');
33 33 var input = $('<div></div>').addClass('input hbox');
34 34 input.append($('<div/>').addClass('prompt input_prompt'));
35 35 var input_area = $('<div/>').addClass('input_area box-flex1');
36 36 this.code_mirror = CodeMirror(input_area.get(0), {
37 37 indentUnit : 4,
38 38 mode: 'python',
39 39 theme: 'ipython',
40 40 readOnly: this.read_only,
41 41 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
42 42 });
43 43 input.append(input_area);
44 44 var output = $('<div></div>').addClass('output vbox');
45 45 cell.append(input).append(output);
46 46 this.element = cell;
47 47 this.collapse()
48 48 };
49 49
50 50 //TODO, try to diminish the number of parameters.
51 51 CodeCell.prototype.request_tooltip_after_time = function (pre_cursor,time,that){
52 52 if (pre_cursor === "" || pre_cursor === "(" ) {
53 53 // don't do anything if line beggin with '(' or is empty
54 54 } else {
55 55 // Will set a timer to request tooltip in `time`
56 56 that.tooltip_timeout = setTimeout(function(){
57 57 IPython.notebook.request_tool_tip(that, pre_cursor)
58 58 },time);
59 59 }
60 60 };
61 61
62 62 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
63 63 // This method gets called in CodeMirror's onKeyDown/onKeyPress
64 64 // handlers and is used to provide custom key handling. Its return
65 65 // value is used to determine if CodeMirror should ignore the event:
66 66 // true = ignore, false = don't ignore.
67 67
68 68 // note that we are comparing and setting the time to wait at each key press.
69 69 // a better wqy might be to generate a new function on each time change and
70 70 // assign it to CodeCell.prototype.request_tooltip_after_time
71 71 tooltip_wait_time = this.notebook.time_before_tooltip;
72 72 tooltip_on_tab = this.notebook.tooltip_on_tab;
73 73 var that = this;
74 74 // whatever key is pressed, first, cancel the tooltip request before
75 75 // they are sent, and remove tooltip if any
76 76 if(event.type === 'keydown' && this.tooltip_timeout != null){
77 77 CodeCell.prototype.remove_and_cancell_tooltip(that.tooltip_timeout);
78 78 that.tooltip_timeout=null;
79 79 }
80 80
81 81 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
82 82 // Always ignore shift-enter in CodeMirror as we handle it.
83 83 return true;
84 84 }else if (event.which === 40 && event.type === 'keypress' && tooltip_wait_time >= 0) {
85 85 // triger aon keypress (!) otherwise inconsistent event.which depending on plateform
86 86 // browser and keyboard layout !
87 87 // Pressing '(' , request tooltip, don't forget to reappend it
88 88 var cursor = editor.getCursor();
89 89 var pre_cursor = editor.getRange({line:cursor.line,ch:0},cursor).trim()+'(';
90 90 CodeCell.prototype.request_tooltip_after_time(pre_cursor,tooltip_wait_time,that);
91 91 } else if (event.keyCode === 9 && event.type == 'keydown') {
92 92 // Tab completion.
93 93 var cur = editor.getCursor();
94 94 //Do not trim here because of tooltip
95 95 var pre_cursor = editor.getRange({line:cur.line,ch:0},cur);
96 96 if (pre_cursor.trim() === "") {
97 97 // Don't autocomplete if the part of the line before the cursor
98 98 // is empty. In this case, let CodeMirror handle indentation.
99 99 return false;
100 100 } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && tooltip_on_tab ) {
101 101 CodeCell.prototype.request_tooltip_after_time(pre_cursor,0,that);
102 102 } else {
103 103 pre_cursor.trim();
104 104 // Autocomplete the current line.
105 105 event.stop();
106 106 var line = editor.getLine(cur.line);
107 107 this.is_completing = true;
108 108 this.completion_cursor = cur;
109 109 IPython.notebook.complete_cell(this, line, cur.ch);
110 110 return true;
111 111 }
112 112 } else if (event.keyCode === 8 && event.type == 'keydown') {
113 113 // If backspace and the line ends with 4 spaces, remove them.
114 114 var cur = editor.getCursor();
115 115 var line = editor.getLine(cur.line);
116 116 var ending = line.slice(-4);
117 117 if (ending === ' ') {
118 118 editor.replaceRange('',
119 119 {line: cur.line, ch: cur.ch-4},
120 120 {line: cur.line, ch: cur.ch}
121 121 );
122 122 event.stop();
123 123 return true;
124 124 } else {
125 125 return false;
126 126 };
127 127 } else if (event.keyCode === 76 && event.ctrlKey && event.shiftKey
128 128 && event.type == 'keydown') {
129 129 // toggle line numbers with Ctrl-Shift-L
130 130 this.toggle_line_numbers();
131 131 }
132 132 else {
133 133 // keypress/keyup also trigger on TAB press, and we don't want to
134 134 // use those to disable tab completion.
135 135 if (this.is_completing && event.keyCode !== 9) {
136 136 var ed_cur = editor.getCursor();
137 137 var cc_cur = this.completion_cursor;
138 138 if (ed_cur.line !== cc_cur.line || ed_cur.ch !== cc_cur.ch) {
139 139 this.is_completing = false;
140 140 this.completion_cursor = null;
141 141 };
142 142 };
143 143 return false;
144 144 };
145 145 };
146 146
147 147 CodeCell.prototype.remove_and_cancell_tooltip = function(timeout)
148 148 {
149 149 // note that we don't handle closing directly inside the calltip
150 150 // as in the completer, because it is not focusable, so won't
151 151 // get the event.
152 152 clearTimeout(timeout);
153 153 $('#tooltip').remove();
154 154 }
155 155
156 156 CodeCell.prototype.finish_tooltip = function (reply) {
157 157 defstring=reply.definition;
158 158 docstring=reply.docstring;
159 159 if(docstring == null){docstring="<empty docstring>"};
160 160 name=reply.name;
161 161
162 162 var that = this;
163 163 var tooltip = $('<div/>').attr('id', 'tooltip').addClass('tooltip');
164 164 // remove to have the tooltip not Limited in X and Y
165 165 tooltip.addClass('smalltooltip');
166 166 var pre=$('<pre/>').html(utils.fixConsole(docstring));
167 167 var expandlink=$('<a/>').attr('href',"#");
168 168 expandlink.addClass("ui-corner-all"); //rounded corner
169 169 expandlink.attr('role',"button");
170 170 //expandlink.addClass('ui-button');
171 171 //expandlink.addClass('ui-state-default');
172 172 var expandspan=$('<span/>').text('Expand');
173 173 expandspan.addClass('ui-icon');
174 174 expandspan.addClass('ui-icon-plus');
175 175 expandlink.append(expandspan);
176 176 expandlink.attr('id','expanbutton');
177 177 expandlink.click(function(){
178 178 tooltip.removeClass('smalltooltip');
179 179 tooltip.addClass('bigtooltip');
180 180 $('#expanbutton').remove();
181 181 setTimeout(function(){that.code_mirror.focus();}, 50);
182 182 });
183 183 var morelink=$('<a/>').attr('href',"#");
184 184 morelink.attr('role',"button");
185 185 morelink.addClass('ui-button');
186 186 //morelink.addClass("ui-corner-all"); //rounded corner
187 187 //morelink.addClass('ui-state-default');
188 188 var morespan=$('<span/>').text('Open in Pager');
189 189 morespan.addClass('ui-icon');
190 190 morespan.addClass('ui-icon-arrowstop-l-n');
191 191 morelink.append(morespan);
192 192 morelink.click(function(){
193 193 var msg_id = IPython.notebook.kernel.execute(name+"?");
194 194 IPython.notebook.msg_cell_map[msg_id] = IPython.notebook.selected_cell().cell_id;
195 195 CodeCell.prototype.remove_and_cancell_tooltip(that.tooltip_timeout);
196 196 setTimeout(function(){that.code_mirror.focus();}, 50);
197 197 });
198 198
199 199 var closelink=$('<a/>').attr('href',"#");
200 200 closelink.attr('role',"button");
201 201 closelink.addClass('ui-button');
202 202 //closelink.addClass("ui-corner-all"); //rounded corner
203 203 //closelink.adClass('ui-state-default'); // grey background and blue cross
204 204 var closespan=$('<span/>').text('Close');
205 205 closespan.addClass('ui-icon');
206 206 closespan.addClass('ui-icon-close');
207 207 closelink.append(closespan);
208 208 closelink.click(function(){
209 209 CodeCell.prototype.remove_and_cancell_tooltip(that.tooltip_timeout);
210 210 setTimeout(function(){that.code_mirror.focus();}, 50);
211 211 });
212 212 //construct the tooltip
213 213 tooltip.append(closelink);
214 214 tooltip.append(expandlink);
215 215 tooltip.append(morelink);
216 216 if(defstring){
217 217 defstring_html= $('<pre/>').html(utils.fixConsole(defstring));
218 218 tooltip.append(defstring_html);
219 219 }
220 220 tooltip.append(pre);
221 221 var pos = this.code_mirror.cursorCoords();
222 222 tooltip.css('left',pos.x+'px');
223 223 tooltip.css('top',pos.yBot+'px');
224 224 $('body').append(tooltip);
225 225
226 226 // issues with cross-closing if multiple tooltip in less than 5sec
227 227 // keep it comented for now
228 228 // setTimeout(CodeCell.prototype.remove_and_cancell_tooltip, 5000);
229 229 };
230 230
231 231
232 232 CodeCell.prototype.finish_completing = function (matched_text, matches) {
233 233 // console.log("Got matches", matched_text, matches);
234 234 var newm = new Array();
235 235 if(this.notebook.smart_completer)
236 236 {
237 237 kwargs = new Array();
238 238 other = new Array();
239 239 for(var i=0;i<matches.length; ++i){
240 240 if(matches[i].substr(-1) === '='){
241 241 kwargs.push(matches[i]);
242 242 }else{other.push(matches[i]);}
243 243 }
244 244 newm = kwargs.concat(other);
245 245 matches=newm;
246 246 }
247 247 if (!this.is_completing || matches.length === 0) {return;}
248 248
249 249 //try to check if the user is typing tab at least twice after a word
250 250 // and completion is "done"
251 251 fallback_on_tooltip_after=2
252 252 if(matches.length==1 && matched_text === matches[0])
253 253 {
254 254 if(this.npressed >fallback_on_tooltip_after && this.prevmatch==matched_text)
255 255 {
256 256 console.log('Ok, you really want to complete after pressing tab '+this.npressed+' times !');
257 257 console.log('You should understand that there is no (more) completion for that !');
258 258 console.log("I'll show you the tooltip, will you stop bothering me ?");
259 259 this.request_tooltip_after_time(matched_text+'(',0,this);
260 260 return;
261 261 }
262 262 this.prevmatch=matched_text
263 263 this.npressed=this.npressed+1;
264 264 }
265 265 else
266 266 {
267 267 this.prevmatch="";
268 268 this.npressed=0;
269 269 }
270 270
271 271 var that = this;
272 272 var cur = this.completion_cursor;
273 273
274 274 var insert = function (selected_text) {
275 275 that.code_mirror.replaceRange(
276 276 selected_text,
277 277 {line: cur.line, ch: (cur.ch-matched_text.length)},
278 278 {line: cur.line, ch: cur.ch}
279 279 );
280 280 };
281 281
282 282 if (matches.length === 1) {
283 283 insert(matches[0]);
284 284 setTimeout(function(){that.code_mirror.focus();}, 50);
285 285 return;
286 286 };
287 287
288 288 var complete = $('<div/>').addClass('completions');
289 289 var select = $('<select/>').attr('multiple','true');
290 290 for (var i=0; i<matches.length; ++i) {
291 291 select.append($('<option/>').text(matches[i]));
292 292 }
293 293 select.children().first().attr('selected','true');
294 294 select.attr('size',Math.min(10,matches.length));
295 295 var pos = this.code_mirror.cursorCoords();
296 296 complete.css('left',pos.x+'px');
297 297 complete.css('top',pos.yBot+'px');
298 298 complete.append(select);
299 299
300 300 $('body').append(complete);
301 301 var done = false;
302 302
303 303 var close = function () {
304 304 if (done) return;
305 305 done = true;
306 306 complete.remove();
307 307 that.is_completing = false;
308 308 that.completion_cursor = null;
309 309 };
310 310
311 311 var pick = function () {
312 312 insert(select.val()[0]);
313 313 close();
314 314 setTimeout(function(){that.code_mirror.focus();}, 50);
315 315 };
316 316
317 317 select.blur(close);
318 318 select.keydown(function (event) {
319 319 var code = event.which;
320 320 if (code === 13 || code === 32) {
321 321 // Pressing SPACE or ENTER will cause a pick
322 322 event.stopPropagation();
323 323 event.preventDefault();
324 324 pick();
325 325 } else if (code === 38 || code === 40) {
326 326 // We don't want the document keydown handler to handle UP/DOWN,
327 327 // but we want the default action.
328 328 event.stopPropagation();
329 329 } else {
330 330 // All other key presses exit completion.
331 331 event.stopPropagation();
332 332 event.preventDefault();
333 333 close();
334 334 that.code_mirror.focus();
335 335 }
336 336 });
337 337 // Double click also causes a pick.
338 338 select.dblclick(pick);
339 339 select.focus();
340 340 };
341 341
342 342 CodeCell.prototype.toggle_line_numbers = function () {
343 343 if (this.code_mirror.getOption('lineNumbers') == false) {
344 344 this.code_mirror.setOption('lineNumbers', true);
345 345 } else {
346 346 this.code_mirror.setOption('lineNumbers', false);
347 347 }
348 348 this.code_mirror.refresh()
349 349 };
350 350
351 351 CodeCell.prototype.select = function () {
352 352 IPython.Cell.prototype.select.apply(this);
353 353 // Todo: this dance is needed because as of CodeMirror 2.12, focus is
354 354 // not causing the cursor to blink if the editor is empty initially.
355 355 // While this seems to fix the issue, this should be fixed
356 356 // in CodeMirror proper.
357 357 var s = this.code_mirror.getValue();
358 358 this.code_mirror.focus();
359 359 if (s === '') this.code_mirror.setValue('');
360 360 };
361 361
362 362
363 363 CodeCell.prototype.select_all = function () {
364 364 var start = {line: 0, ch: 0};
365 365 var nlines = this.code_mirror.lineCount();
366 366 var last_line = this.code_mirror.getLine(nlines-1);
367 367 var end = {line: nlines-1, ch: last_line.length};
368 368 this.code_mirror.setSelection(start, end);
369 369 };
370 370
371 371
372 372 CodeCell.prototype.append_output = function (json) {
373 373 this.expand();
374 374 if (json.output_type === 'pyout') {
375 375 this.append_pyout(json);
376 376 } else if (json.output_type === 'pyerr') {
377 377 this.append_pyerr(json);
378 378 } else if (json.output_type === 'display_data') {
379 379 this.append_display_data(json);
380 380 } else if (json.output_type === 'stream') {
381 381 this.append_stream(json);
382 382 };
383 383 this.outputs.push(json);
384 384 };
385 385
386 386
387 387 CodeCell.prototype.create_output_area = function () {
388 388 var oa = $("<div/>").addClass("hbox output_area");
389 389 oa.append($('<div/>').addClass('prompt'));
390 390 return oa;
391 391 };
392 392
393 393
394 394 CodeCell.prototype.append_pyout = function (json) {
395 395 n = json.prompt_number || ' ';
396 396 var toinsert = this.create_output_area();
397 397 toinsert.find('div.prompt').addClass('output_prompt').html('Out[' + n + ']:');
398 398 this.append_mime_type(json, toinsert);
399 399 this.element.find('div.output').append(toinsert);
400 400 // If we just output latex, typeset it.
401 401 if ((json.latex !== undefined) || (json.html !== undefined)) {
402 402 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
403 403 };
404 404 };
405 405
406 406
407 407 CodeCell.prototype.append_pyerr = function (json) {
408 408 var tb = json.traceback;
409 409 if (tb !== undefined && tb.length > 0) {
410 410 var s = '';
411 411 var len = tb.length;
412 412 for (var i=0; i<len; i++) {
413 413 s = s + tb[i] + '\n';
414 414 }
415 415 s = s + '\n';
416 416 var toinsert = this.create_output_area();
417 417 this.append_text(s, toinsert);
418 418 this.element.find('div.output').append(toinsert);
419 419 };
420 420 };
421 421
422 422
423 423 CodeCell.prototype.append_stream = function (json) {
424 424 // temporary fix: if stream undefined (json file written prior to this patch),
425 425 // default to most likely stdout:
426 426 if (json.stream == undefined){
427 427 json.stream = 'stdout';
428 428 }
429 429 var subclass = "output_"+json.stream;
430 430 if (this.outputs.length > 0){
431 431 // have at least one output to consider
432 432 var last = this.outputs[this.outputs.length-1];
433 433 if (last.output_type == 'stream' && json.stream == last.stream){
434 434 // latest output was in the same stream,
435 435 // so append directly into its pre tag
436 436 this.element.find('div.'+subclass).last().find('pre').append(json.text);
437 437 return;
438 438 }
439 439 }
440 440
441 441 // If we got here, attach a new div
442 442 var toinsert = this.create_output_area();
443 443 this.append_text(json.text, toinsert, "output_stream "+subclass);
444 444 this.element.find('div.output').append(toinsert);
445 445 };
446 446
447 447
448 448 CodeCell.prototype.append_display_data = function (json) {
449 449 var toinsert = this.create_output_area();
450 450 this.append_mime_type(json, toinsert)
451 451 this.element.find('div.output').append(toinsert);
452 452 // If we just output latex, typeset it.
453 453 if ( (json.latex !== undefined) || (json.html !== undefined) ) {
454 454 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
455 455 };
456 456 };
457 457
458 458
459 459 CodeCell.prototype.append_mime_type = function (json, element) {
460 460 if (json.html !== undefined) {
461 461 this.append_html(json.html, element);
462 462 } else if (json.latex !== undefined) {
463 463 this.append_latex(json.latex, element);
464 464 } else if (json.svg !== undefined) {
465 465 this.append_svg(json.svg, element);
466 466 } else if (json.png !== undefined) {
467 467 this.append_png(json.png, element);
468 468 } else if (json.jpeg !== undefined) {
469 469 this.append_jpeg(json.jpeg, element);
470 470 } else if (json.text !== undefined) {
471 471 this.append_text(json.text, element);
472 472 };
473 473 };
474 474
475 475
476 476 CodeCell.prototype.append_html = function (html, element) {
477 477 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_html rendered_html");
478 478 toinsert.append(html);
479 479 element.append(toinsert);
480 480 }
481 481
482 482
483 483 CodeCell.prototype.append_text = function (data, element, extra_class) {
484 484 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_text");
485 485 if (extra_class){
486 486 toinsert.addClass(extra_class);
487 487 }
488 488 toinsert.append($("<pre/>").html(data));
489 489 element.append(toinsert);
490 490 };
491 491
492 492
493 493 CodeCell.prototype.append_svg = function (svg, element) {
494 494 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_svg");
495 495 toinsert.append(svg);
496 496 element.append(toinsert);
497 497 };
498 498
499 499
500 500 CodeCell.prototype.append_png = function (png, element) {
501 501 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_png");
502 502 toinsert.append($("<img/>").attr('src','data:image/png;base64,'+png));
503 503 element.append(toinsert);
504 504 };
505 505
506 506
507 507 CodeCell.prototype.append_jpeg = function (jpeg, element) {
508 508 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_jpeg");
509 509 toinsert.append($("<img/>").attr('src','data:image/jpeg;base64,'+jpeg));
510 510 element.append(toinsert);
511 511 };
512 512
513 513
514 514 CodeCell.prototype.append_latex = function (latex, element) {
515 515 // This method cannot do the typesetting because the latex first has to
516 516 // be on the page.
517 517 var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_latex");
518 518 toinsert.append(latex);
519 519 element.append(toinsert);
520 520 }
521 521
522 522
523 523 CodeCell.prototype.clear_output = function (stdout, stderr, other) {
524 524 var output_div = this.element.find("div.output");
525 525 if (stdout && stderr && other){
526 526 // clear all, no need for logic
527 527 output_div.html("");
528 528 this.outputs = [];
529 529 return;
530 530 }
531 531 // remove html output
532 532 // each output_subarea that has an identifying class is in an output_area
533 533 // which is the element to be removed.
534 534 if (stdout){
535 535 output_div.find("div.output_stdout").parent().remove();
536 536 }
537 537 if (stderr){
538 538 output_div.find("div.output_stderr").parent().remove();
539 539 }
540 540 if (other){
541 541 output_div.find("div.output_subarea").not("div.output_stderr").not("div.output_stdout").parent().remove();
542 542 }
543 543
544 544 // remove cleared outputs from JSON list:
545 545 for (var i = this.outputs.length - 1; i >= 0; i--){
546 546 var out = this.outputs[i];
547 547 var output_type = out.output_type;
548 548 if (output_type == "display_data" && other){
549 549 this.outputs.splice(i,1);
550 550 }else if (output_type == "stream"){
551 551 if (stdout && out.stream == "stdout"){
552 552 this.outputs.splice(i,1);
553 553 }else if (stderr && out.stream == "stderr"){
554 554 this.outputs.splice(i,1);
555 555 }
556 556 }
557 557 }
558 558 };
559 559
560 560
561 561 CodeCell.prototype.clear_input = function () {
562 562 this.code_mirror.setValue('');
563 563 };
564 564
565 565
566 566 CodeCell.prototype.collapse = function () {
567 567 if (!this.collapsed) {
568 568 this.element.find('div.output').hide();
569 569 this.collapsed = true;
570 570 };
571 571 };
572 572
573 573
574 574 CodeCell.prototype.expand = function () {
575 575 if (this.collapsed) {
576 576 this.element.find('div.output').show();
577 577 this.collapsed = false;
578 578 };
579 579 };
580 580
581 581
582 582 CodeCell.prototype.toggle_output = function () {
583 583 if (this.collapsed) {
584 584 this.expand();
585 585 } else {
586 586 this.collapse();
587 587 };
588 588 };
589 589
590 590 CodeCell.prototype.set_input_prompt = function (number) {
591 var n = number || ' ';
591 var n = number || '&nbsp;';
592 592 this.input_prompt_number = n
593 593 this.element.find('div.input_prompt').html('In&nbsp;[' + n + ']:');
594 594 };
595 595
596 596
597 597 CodeCell.prototype.get_code = function () {
598 598 return this.code_mirror.getValue();
599 599 };
600 600
601 601
602 602 CodeCell.prototype.set_code = function (code) {
603 603 return this.code_mirror.setValue(code);
604 604 };
605 605
606 606
607 607 CodeCell.prototype.at_top = function () {
608 608 var cursor = this.code_mirror.getCursor();
609 609 if (cursor.line === 0) {
610 610 return true;
611 611 } else {
612 612 return false;
613 613 }
614 614 };
615 615
616 616
617 617 CodeCell.prototype.at_bottom = function () {
618 618 var cursor = this.code_mirror.getCursor();
619 619 if (cursor.line === (this.code_mirror.lineCount()-1)) {
620 620 return true;
621 621 } else {
622 622 return false;
623 623 }
624 624 };
625 625
626 626
627 627 CodeCell.prototype.fromJSON = function (data) {
628 628 console.log('Import from JSON:', data);
629 629 if (data.cell_type === 'code') {
630 630 if (data.input !== undefined) {
631 631 this.set_code(data.input);
632 632 }
633 633 if (data.prompt_number !== undefined) {
634 634 this.set_input_prompt(data.prompt_number);
635 635 } else {
636 636 this.set_input_prompt();
637 637 };
638 638 var len = data.outputs.length;
639 639 for (var i=0; i<len; i++) {
640 640 this.append_output(data.outputs[i]);
641 641 };
642 642 if (data.collapsed !== undefined) {
643 643 if (data.collapsed) {
644 644 this.collapse();
645 645 };
646 646 };
647 647 };
648 648 };
649 649
650 650
651 651 CodeCell.prototype.toJSON = function () {
652 652 var data = {};
653 653 data.input = this.get_code();
654 654 data.cell_type = 'code';
655 655 if (this.input_prompt_number !== ' ') {
656 656 data.prompt_number = this.input_prompt_number
657 657 };
658 658 var outputs = [];
659 659 var len = this.outputs.length;
660 660 for (var i=0; i<len; i++) {
661 661 outputs[i] = this.outputs[i];
662 662 };
663 663 data.outputs = outputs;
664 664 data.language = 'python';
665 665 data.collapsed = this.collapsed;
666 666 // console.log('Export to JSON:',data);
667 667 return data;
668 668 };
669 669
670 670
671 671 IPython.CodeCell = CodeCell;
672 672
673 673 return IPython;
674 674 }(IPython));
General Comments 0
You need to be logged in to leave comments. Login now