##// END OF EJS Templates
Fixing console.log messages related to keyboard shortcuts.
Brian E. Granger -
Show More
@@ -1,932 +1,930
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 // Notebook
10 10 //============================================================================
11 11
12 12 var IPython = (function (IPython) {
13 13
14 14 var utils = IPython.utils;
15 15
16 16 var Notebook = function (selector) {
17 17 this.element = $(selector);
18 18 this.element.scroll();
19 19 this.element.data("notebook", this);
20 20 this.next_prompt_number = 1;
21 21 this.kernel = null;
22 22 this.dirty = false;
23 23 this.msg_cell_map = {};
24 24 this.metadata = {};
25 25 this.control_key_active = false;
26 26 this.style();
27 27 this.create_elements();
28 28 this.bind_events();
29 29 };
30 30
31 31
32 32 Notebook.prototype.style = function () {
33 33 $('div#notebook').addClass('border-box-sizing');
34 34 };
35 35
36 36
37 37 Notebook.prototype.create_elements = function () {
38 38 // We add this end_space div to the end of the notebook div to:
39 39 // i) provide a margin between the last cell and the end of the notebook
40 40 // ii) to prevent the div from scrolling up when the last cell is being
41 41 // edited, but is too low on the page, which browsers will do automatically.
42 42 var that = this;
43 43 var end_space = $('<div class="end_space"></div>').height(150);
44 44 end_space.dblclick(function (e) {
45 45 var ncells = that.ncells();
46 46 that.insert_code_cell_after(ncells-1);
47 47 });
48 48 this.element.append(end_space);
49 49 $('div#notebook').addClass('border-box-sizing');
50 50 };
51 51
52 52
53 53 Notebook.prototype.bind_events = function () {
54 54 var that = this;
55 55 $(document).keydown(function (event) {
56 console.log(event);
56 // console.log(event);
57 57 if (event.which === 38) {
58 58 var cell = that.selected_cell();
59 59 if (cell.at_top()) {
60 60 event.preventDefault();
61 61 that.select_prev();
62 62 };
63 63 } else if (event.which === 40) {
64 64 var cell = that.selected_cell();
65 65 if (cell.at_bottom()) {
66 66 event.preventDefault();
67 67 that.select_next();
68 68 };
69 69 } else if (event.which === 13 && event.shiftKey) {
70 70 that.execute_selected_cell();
71 71 return false;
72 72 } else if (event.which === 13 && event.ctrlKey) {
73 73 that.execute_selected_cell({terminal:true});
74 74 return false;
75 75 } else if (event.which === 77 && event.ctrlKey) {
76 console.log("Activating control key")
77 76 that.control_key_active = true;
78 77 return false;
79 78 } else if (event.which === 68 && that.control_key_active) {
80 79 // Delete selected cell = d
81 80 that.delete_cell();
82 81 that.control_key_active = false;
83 82 return false;
84 83 } else if (event.which === 65 && that.control_key_active) {
85 84 // Insert code cell after selected = a
86 85 that.insert_code_cell_after();
87 86 that.control_key_active = false;
88 87 return false;
89 88 } else if (event.which === 66 && that.control_key_active) {
90 89 // Insert code cell before selected = b
91 90 that.insert_code_cell_before();
92 91 that.control_key_active = false;
93 92 return false;
94 93 } else if (event.which === 67 && that.control_key_active) {
95 94 // To code = c
96 95 that.to_code();
97 96 that.control_key_active = false;
98 97 return false;
99 98 } else if (event.which === 77 && that.control_key_active) {
100 99 // To markdown = m
101 100 that.to_markdown();
102 101 that.control_key_active = false;
103 102 return false;
104 103 } else if (event.which === 84 && that.control_key_active) {
105 104 // Toggle output = t
106 105 that.toggle_output();
107 106 that.control_key_active = false;
108 107 return false;
109 108 } else if (event.which === 83 && that.control_key_active) {
110 109 // Save notebook = s
111 110 IPython.save_widget.save_notebook();
112 111 that.control_key_active = false;
113 112 return false;
114 113 } else if (event.which === 74 && that.control_key_active) {
115 114 // Move cell down = j
116 115 that.move_cell_down();
117 116 that.control_key_active = false;
118 117 return false;
119 118 } else if (event.which === 75 && that.control_key_active) {
120 119 // Move cell up = k
121 120 that.move_cell_up();
122 121 that.control_key_active = false;
123 122 return false;
124 123 } else if (event.which === 38 && that.control_key_active) {
125 124 // Select previous = up arrow
126 125 that.select_prev();
127 126 that.control_key_active = false;
128 127 return false;
129 128 } else if (event.which === 40 && that.control_key_active) {
130 129 // Select next = down arrow
131 130 that.select_next();
132 131 that.control_key_active = false;
133 132 return false;
134 133 } else if (event.which === 72 && that.control_key_active) {
135 134 // Show keyboard shortcuts = h
136 135 that.show_keyboard_shortcuts();
137 136 that.control_key_active = false;
138 137 return false;
139 138 } else if (that.control_key_active) {
140 139 that.control_key_active = false;
141 140 return true;
142 141 };
143 142 });
144 143
145 144 this.element.bind('collapse_pager', function () {
146 145 var app_height = $('div#main_app').height(); // content height
147 146 var splitter_height = $('div#pager_splitter').outerHeight(true);
148 147 var new_height = app_height - splitter_height;
149 148 that.element.animate({height : new_height + 'px'}, 'fast');
150 149 });
151 150
152 151 this.element.bind('expand_pager', function () {
153 152 var app_height = $('div#main_app').height(); // content height
154 153 var splitter_height = $('div#pager_splitter').outerHeight(true);
155 154 var pager_height = $('div#pager').outerHeight(true);
156 155 var new_height = app_height - pager_height - splitter_height;
157 156 that.element.animate({height : new_height + 'px'}, 'fast');
158 157 });
159 158
160 159 this.element.bind('collapse_left_panel', function () {
161 160 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
162 161 var new_margin = splitter_width;
163 162 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
164 163 });
165 164
166 165 this.element.bind('expand_left_panel', function () {
167 166 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
168 167 var left_panel_width = IPython.left_panel.width;
169 168 var new_margin = splitter_width + left_panel_width;
170 169 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
171 170 });
172 171
173 172 $(window).bind('beforeunload', function () {
174 173 var kill_kernel = $('#kill_kernel').prop('checked');
175 174 if (kill_kernel) {
176 175 that.kernel.kill();
177 176 }
178 177 if (that.dirty) {
179 178 return "You have unsaved changes that will be lost if you leave this page.";
180 179 };
181 180 });
182 181 };
183 182
184 183
185 184 Notebook.prototype.show_keyboard_shortcuts = function () {
186 console.log('showing');
187 185 var dialog = $('<div/>');
188 186 var shortcuts = [
189 187 {key: 'Shift-Enter', help: 'run cell'},
190 188 {key: 'Ctrl-Enter', help: 'run cell in terminal mode'},
191 189 {key: 'Ctrl-m d', help: 'delete cell'},
192 190 {key: 'Ctrl-m a', help: 'insert cell above'},
193 191 {key: 'Ctrl-m b', help: 'insert cell below'},
194 192 {key: 'Ctrl-m t', help: 'toggle output'},
195 193 {key: 'Ctrl-m s', help: 'save notebook'},
196 194 {key: 'Ctrl-m j', help: 'move cell down'},
197 195 {key: 'Ctrl-m k', help: 'move cell up'},
198 196 {key: 'Ctrl-m c', help: 'code cell'},
199 197 {key: 'Ctrl-m m', help: 'markdown cell'},
200 198 {key: 'Ctrl-m up', help: 'select previous'},
201 199 {key: 'Ctrl-m down', help: 'select next'},
202 200 {key: 'Ctrl-m h', help: 'display keyboard shortcuts'}
203 201 ];
204 202 for (var i=0; i<shortcuts.length; i++) {
205 203 dialog.append($('<div>').
206 204 append($('<span/>').addClass('shortcut_key').html(shortcuts[i].key+' : ')).
207 205 append($('<span/>').html(shortcuts[i].help))
208 206 );
209 207 };
210 208 dialog.dialog({title: 'Keyboard shortcuts'});
211 209 };
212 210
213 211
214 212 Notebook.prototype.scroll_to_bottom = function () {
215 213 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
216 214 };
217 215
218 216
219 217 Notebook.prototype.scroll_to_top = function () {
220 218 this.element.animate({scrollTop:0}, 0);
221 219 };
222 220
223 221
224 222 // Cell indexing, retrieval, etc.
225 223
226 224
227 225 Notebook.prototype.cell_elements = function () {
228 226 return this.element.children("div.cell");
229 227 }
230 228
231 229
232 230 Notebook.prototype.ncells = function (cell) {
233 231 return this.cell_elements().length;
234 232 }
235 233
236 234
237 235 // TODO: we are often calling cells as cells()[i], which we should optimize
238 236 // to cells(i) or a new method.
239 237 Notebook.prototype.cells = function () {
240 238 return this.cell_elements().toArray().map(function (e) {
241 239 return $(e).data("cell");
242 240 });
243 241 }
244 242
245 243
246 244 Notebook.prototype.find_cell_index = function (cell) {
247 245 var result = null;
248 246 this.cell_elements().filter(function (index) {
249 247 if ($(this).data("cell") === cell) {
250 248 result = index;
251 249 };
252 250 });
253 251 return result;
254 252 };
255 253
256 254
257 255 Notebook.prototype.index_or_selected = function (index) {
258 256 return index || this.selected_index() || 0;
259 257 }
260 258
261 259
262 260 Notebook.prototype.select = function (index) {
263 261 if (index !== undefined && index >= 0 && index < this.ncells()) {
264 262 if (this.selected_index() !== null) {
265 263 this.selected_cell().unselect();
266 264 };
267 265 this.cells()[index].select();
268 266 };
269 267 return this;
270 268 };
271 269
272 270
273 271 Notebook.prototype.select_next = function () {
274 272 var index = this.selected_index();
275 273 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
276 274 this.select(index+1);
277 275 };
278 276 return this;
279 277 };
280 278
281 279
282 280 Notebook.prototype.select_prev = function () {
283 281 var index = this.selected_index();
284 282 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
285 283 this.select(index-1);
286 284 };
287 285 return this;
288 286 };
289 287
290 288
291 289 Notebook.prototype.selected_index = function () {
292 290 var result = null;
293 291 this.cell_elements().filter(function (index) {
294 292 if ($(this).data("cell").selected === true) {
295 293 result = index;
296 294 };
297 295 });
298 296 return result;
299 297 };
300 298
301 299
302 300 Notebook.prototype.cell_for_msg = function (msg_id) {
303 301 var cell_id = this.msg_cell_map[msg_id];
304 302 var result = null;
305 303 this.cell_elements().filter(function (index) {
306 304 cell = $(this).data("cell");
307 305 if (cell.cell_id === cell_id) {
308 306 result = cell;
309 307 };
310 308 });
311 309 return result;
312 310 };
313 311
314 312
315 313 Notebook.prototype.selected_cell = function () {
316 314 return this.cell_elements().eq(this.selected_index()).data("cell");
317 315 }
318 316
319 317
320 318 // Cell insertion, deletion and moving.
321 319
322 320
323 321 Notebook.prototype.delete_cell = function (index) {
324 322 var i = index || this.selected_index();
325 323 if (i !== null && i >= 0 && i < this.ncells()) {
326 324 this.cell_elements().eq(i).remove();
327 325 if (i === (this.ncells())) {
328 326 this.select(i-1);
329 327 } else {
330 328 this.select(i);
331 329 };
332 330 };
333 331 this.dirty = true;
334 332 return this;
335 333 };
336 334
337 335
338 336 Notebook.prototype.append_cell = function (cell) {
339 337 this.element.find('div.end_space').before(cell.element);
340 338 this.dirty = true;
341 339 return this;
342 340 };
343 341
344 342
345 343 Notebook.prototype.insert_cell_after = function (cell, index) {
346 344 var ncells = this.ncells();
347 345 if (ncells === 0) {
348 346 this.append_cell(cell);
349 347 return this;
350 348 };
351 349 if (index >= 0 && index < ncells) {
352 350 this.cell_elements().eq(index).after(cell.element);
353 351 };
354 352 this.dirty = true;
355 353 return this
356 354 };
357 355
358 356
359 357 Notebook.prototype.insert_cell_before = function (cell, index) {
360 358 var ncells = this.ncells();
361 359 if (ncells === 0) {
362 360 this.append_cell(cell);
363 361 return this;
364 362 };
365 363 if (index >= 0 && index < ncells) {
366 364 this.cell_elements().eq(index).before(cell.element);
367 365 };
368 366 this.dirty = true;
369 367 return this;
370 368 };
371 369
372 370
373 371 Notebook.prototype.move_cell_up = function (index) {
374 372 var i = index || this.selected_index();
375 373 if (i !== null && i < this.ncells() && i > 0) {
376 374 var pivot = this.cell_elements().eq(i-1);
377 375 var tomove = this.cell_elements().eq(i);
378 376 if (pivot !== null && tomove !== null) {
379 377 tomove.detach();
380 378 pivot.before(tomove);
381 379 this.select(i-1);
382 380 };
383 381 };
384 382 this.dirty = true;
385 383 return this;
386 384 }
387 385
388 386
389 387 Notebook.prototype.move_cell_down = function (index) {
390 388 var i = index || this.selected_index();
391 389 if (i !== null && i < (this.ncells()-1) && i >= 0) {
392 390 var pivot = this.cell_elements().eq(i+1)
393 391 var tomove = this.cell_elements().eq(i)
394 392 if (pivot !== null && tomove !== null) {
395 393 tomove.detach();
396 394 pivot.after(tomove);
397 395 this.select(i+1);
398 396 };
399 397 };
400 398 this.dirty = true;
401 399 return this;
402 400 }
403 401
404 402
405 403 Notebook.prototype.sort_cells = function () {
406 404 var ncells = this.ncells();
407 405 var sindex = this.selected_index();
408 406 var swapped;
409 407 do {
410 408 swapped = false
411 409 for (var i=1; i<ncells; i++) {
412 410 current = this.cell_elements().eq(i).data("cell");
413 411 previous = this.cell_elements().eq(i-1).data("cell");
414 412 if (previous.input_prompt_number > current.input_prompt_number) {
415 413 this.move_cell_up(i);
416 414 swapped = true;
417 415 };
418 416 };
419 417 } while (swapped);
420 418 this.select(sindex);
421 419 return this;
422 420 };
423 421
424 422
425 423 Notebook.prototype.insert_code_cell_before = function (index) {
426 424 // TODO: Bounds check for i
427 425 var i = this.index_or_selected(index);
428 426 var cell = new IPython.CodeCell(this);
429 427 cell.set_input_prompt();
430 428 this.insert_cell_before(cell, i);
431 429 this.select(this.find_cell_index(cell));
432 430 return cell;
433 431 }
434 432
435 433
436 434 Notebook.prototype.insert_code_cell_after = function (index) {
437 435 // TODO: Bounds check for i
438 436 var i = this.index_or_selected(index);
439 437 var cell = new IPython.CodeCell(this);
440 438 cell.set_input_prompt();
441 439 this.insert_cell_after(cell, i);
442 440 this.select(this.find_cell_index(cell));
443 441 return cell;
444 442 }
445 443
446 444
447 445 Notebook.prototype.insert_html_cell_before = function (index) {
448 446 // TODO: Bounds check for i
449 447 var i = this.index_or_selected(index);
450 448 var cell = new IPython.HTMLCell(this);
451 449 cell.config_mathjax();
452 450 this.insert_cell_before(cell, i);
453 451 this.select(this.find_cell_index(cell));
454 452 return cell;
455 453 }
456 454
457 455
458 456 Notebook.prototype.insert_html_cell_after = function (index) {
459 457 // TODO: Bounds check for i
460 458 var i = this.index_or_selected(index);
461 459 var cell = new IPython.HTMLCell(this);
462 460 cell.config_mathjax();
463 461 this.insert_cell_after(cell, i);
464 462 this.select(this.find_cell_index(cell));
465 463 return cell;
466 464 }
467 465
468 466
469 467 Notebook.prototype.insert_markdown_cell_before = function (index) {
470 468 // TODO: Bounds check for i
471 469 var i = this.index_or_selected(index);
472 470 var cell = new IPython.MarkdownCell(this);
473 471 cell.config_mathjax();
474 472 this.insert_cell_before(cell, i);
475 473 this.select(this.find_cell_index(cell));
476 474 return cell;
477 475 }
478 476
479 477
480 478 Notebook.prototype.insert_markdown_cell_after = function (index) {
481 479 // TODO: Bounds check for i
482 480 var i = this.index_or_selected(index);
483 481 var cell = new IPython.MarkdownCell(this);
484 482 cell.config_mathjax();
485 483 this.insert_cell_after(cell, i);
486 484 this.select(this.find_cell_index(cell));
487 485 return cell;
488 486 }
489 487
490 488
491 489 Notebook.prototype.to_code = function (index) {
492 490 // TODO: Bounds check for i
493 491 var i = this.index_or_selected(index);
494 492 var source_element = this.cell_elements().eq(i);
495 493 var source_cell = source_element.data("cell");
496 494 if (source_cell instanceof IPython.HTMLCell ||
497 495 source_cell instanceof IPython.MarkdownCell) {
498 496 this.insert_code_cell_after(i);
499 497 var target_cell = this.cells()[i+1];
500 498 target_cell.set_code(source_cell.get_source());
501 499 source_element.remove();
502 500 target_cell.select();
503 501 };
504 502 this.dirty = true;
505 503 };
506 504
507 505
508 506 Notebook.prototype.to_markdown = function (index) {
509 507 // TODO: Bounds check for i
510 508 var i = this.index_or_selected(index);
511 509 var source_element = this.cell_elements().eq(i);
512 510 var source_cell = source_element.data("cell");
513 511 var target_cell = null;
514 512 if (source_cell instanceof IPython.CodeCell) {
515 513 this.insert_markdown_cell_after(i);
516 514 var target_cell = this.cells()[i+1];
517 515 var text = source_cell.get_code();
518 516 } else if (source_cell instanceof IPython.HTMLCell) {
519 517 this.insert_markdown_cell_after(i);
520 518 var target_cell = this.cells()[i+1];
521 519 var text = source_cell.get_source();
522 520 if (text === source_cell.placeholder) {
523 521 text = target_cell.placeholder;
524 522 }
525 523 }
526 524 if (target_cell !== null) {
527 525 if (text === "") {text = target_cell.placeholder;};
528 526 target_cell.set_source(text);
529 527 source_element.remove();
530 528 target_cell.edit();
531 529 }
532 530 this.dirty = true;
533 531 };
534 532
535 533
536 534 Notebook.prototype.to_html = function (index) {
537 535 // TODO: Bounds check for i
538 536 var i = this.index_or_selected(index);
539 537 var source_element = this.cell_elements().eq(i);
540 538 var source_cell = source_element.data("cell");
541 539 var target_cell = null;
542 540 if (source_cell instanceof IPython.CodeCell) {
543 541 this.insert_html_cell_after(i);
544 542 var target_cell = this.cells()[i+1];
545 543 var text = source_cell.get_code();
546 544 } else if (source_cell instanceof IPython.MarkdownCell) {
547 545 this.insert_html_cell_after(i);
548 546 var target_cell = this.cells()[i+1];
549 547 var text = source_cell.get_source();
550 548 if (text === source_cell.placeholder) {
551 549 text = target_cell.placeholder;
552 550 }
553 551 }
554 552 if (target_cell !== null) {
555 553 if (text === "") {text = target_cell.placeholder;};
556 554 target_cell.set_source(text);
557 555 source_element.remove();
558 556 target_cell.edit();
559 557 }
560 558 this.dirty = true;
561 559 };
562 560
563 561
564 562 // Cell collapsing and output clearing
565 563
566 564 Notebook.prototype.collapse = function (index) {
567 565 var i = this.index_or_selected(index);
568 566 this.cells()[i].collapse();
569 567 this.dirty = true;
570 568 };
571 569
572 570
573 571 Notebook.prototype.expand = function (index) {
574 572 var i = this.index_or_selected(index);
575 573 this.cells()[i].expand();
576 574 this.dirty = true;
577 575 };
578 576
579 577
580 578 Notebook.prototype.toggle_output = function (index) {
581 579 var i = this.index_or_selected(index);
582 580 this.cells()[i].toggle_output();
583 581 this.dirty = true;
584 582 };
585 583
586 584
587 585 Notebook.prototype.set_autoindent = function (state) {
588 586 var cells = this.cells();
589 587 len = cells.length;
590 588 for (var i=0; i<len; i++) {
591 589 cells[i].set_autoindent(state)
592 590 };
593 591 };
594 592
595 593
596 594 Notebook.prototype.clear_all_output = function () {
597 595 var ncells = this.ncells();
598 596 var cells = this.cells();
599 597 for (var i=0; i<ncells; i++) {
600 598 if (cells[i] instanceof IPython.CodeCell) {
601 599 cells[i].clear_output();
602 600 }
603 601 };
604 602 this.dirty = true;
605 603 };
606 604
607 605
608 606 // Kernel related things
609 607
610 608 Notebook.prototype.start_kernel = function () {
611 609 this.kernel = new IPython.Kernel();
612 610 var notebook_id = IPython.save_widget.get_notebook_id();
613 611 this.kernel.start(notebook_id, $.proxy(this.kernel_started, this));
614 612 };
615 613
616 614
617 615 Notebook.prototype.restart_kernel = function () {
618 616 var notebook_id = IPython.save_widget.get_notebook_id();
619 617 this.kernel.restart($.proxy(this.kernel_started, this));
620 618 };
621 619
622 620
623 621 Notebook.prototype.kernel_started = function () {
624 622 console.log("Kernel started: ", this.kernel.kernel_id);
625 623 this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
626 624 this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
627 625 };
628 626
629 627
630 628 Notebook.prototype.handle_shell_reply = function (e) {
631 629 reply = $.parseJSON(e.data);
632 630 var header = reply.header;
633 631 var content = reply.content;
634 632 var msg_type = header.msg_type;
635 633 // console.log(reply);
636 634 var cell = this.cell_for_msg(reply.parent_header.msg_id);
637 635 if (msg_type === "execute_reply") {
638 636 cell.set_input_prompt(content.execution_count);
639 637 this.dirty = true;
640 638 } else if (msg_type === "complete_reply") {
641 639 cell.finish_completing(content.matched_text, content.matches);
642 640 };
643 641 var payload = content.payload || [];
644 642 this.handle_payload(cell, payload);
645 643 };
646 644
647 645
648 646 Notebook.prototype.handle_payload = function (cell, payload) {
649 647 var l = payload.length;
650 648 for (var i=0; i<l; i++) {
651 649 if (payload[i].source === 'IPython.zmq.page.page') {
652 650 if (payload[i].text.trim() !== '') {
653 651 IPython.pager.clear();
654 652 IPython.pager.expand();
655 653 IPython.pager.append_text(payload[i].text);
656 654 }
657 655 } else if (payload[i].source === 'IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input') {
658 656 var index = this.find_cell_index(cell);
659 657 var new_cell = this.insert_code_cell_after(index);
660 658 new_cell.set_code(payload[i].text);
661 659 this.dirty = true;
662 660 }
663 661 };
664 662 };
665 663
666 664
667 665 Notebook.prototype.handle_iopub_reply = function (e) {
668 666 reply = $.parseJSON(e.data);
669 667 var content = reply.content;
670 668 // console.log(reply);
671 669 var msg_type = reply.header.msg_type;
672 670 var cell = this.cell_for_msg(reply.parent_header.msg_id);
673 671 var output_types = ['stream','display_data','pyout','pyerr'];
674 672 if (output_types.indexOf(msg_type) >= 0) {
675 673 this.handle_output(cell, msg_type, content);
676 674 } else if (msg_type === 'status') {
677 675 if (content.execution_state === 'busy') {
678 676 IPython.kernel_status_widget.status_busy();
679 677 } else if (content.execution_state === 'idle') {
680 678 IPython.kernel_status_widget.status_idle();
681 679 } else if (content.execution_state === 'dead') {
682 680 this.handle_status_dead();
683 681 };
684 682 }
685 683 };
686 684
687 685
688 686 Notebook.prototype.handle_status_dead = function () {
689 687 var that = this;
690 688 this.kernel.stop_channels();
691 689 var dialog = $('<div/>');
692 690 dialog.html('The kernel has died, would you like to restart it? If you do not restart the kernel, you will be able to save the notebook, but running code will not work until the notebook is reopened.');
693 691 $(document).append(dialog);
694 692 dialog.dialog({
695 693 resizable: false,
696 694 modal: true,
697 695 title: "Dead kernel",
698 696 buttons : {
699 697 "Yes": function () {
700 698 that.start_kernel();
701 699 $(this).dialog('close');
702 700 },
703 701 "No": function () {
704 702 $(this).dialog('close');
705 703 }
706 704 }
707 705 });
708 706 };
709 707
710 708
711 709 Notebook.prototype.handle_output = function (cell, msg_type, content) {
712 710 var json = {};
713 711 json.output_type = msg_type;
714 712 if (msg_type === "stream") {
715 713 json.text = utils.fixConsole(content.data + '\n');
716 714 } else if (msg_type === "display_data") {
717 715 json = this.convert_mime_types(json, content.data);
718 716 } else if (msg_type === "pyout") {
719 717 json.prompt_number = content.execution_count;
720 718 json = this.convert_mime_types(json, content.data);
721 719 } else if (msg_type === "pyerr") {
722 720 json.ename = content.ename;
723 721 json.evalue = content.evalue;
724 722 var traceback = [];
725 723 for (var i=0; i<content.traceback.length; i++) {
726 724 traceback.push(utils.fixConsole(content.traceback[i]));
727 725 }
728 726 json.traceback = traceback;
729 727 };
730 728 cell.append_output(json);
731 729 this.dirty = true;
732 730 };
733 731
734 732
735 733 Notebook.prototype.convert_mime_types = function (json, data) {
736 734 if (data['text/plain'] !== undefined) {
737 735 json.text = utils.fixConsole(data['text/plain']);
738 736 };
739 737 if (data['text/html'] !== undefined) {
740 738 json.html = data['text/html'];
741 739 };
742 740 if (data['image/svg+xml'] !== undefined) {
743 741 json.svg = data['image/svg+xml'];
744 742 };
745 743 if (data['image/png'] !== undefined) {
746 744 json.png = data['image/png'];
747 745 };
748 746 if (data['image/jpeg'] !== undefined) {
749 747 json.jpeg = data['image/jpeg'];
750 748 };
751 749 if (data['text/latex'] !== undefined) {
752 750 json.latex = data['text/latex'];
753 751 };
754 752 if (data['application/json'] !== undefined) {
755 753 json.json = data['application/json'];
756 754 };
757 755 if (data['application/javascript'] !== undefined) {
758 756 json.javascript = data['application/javascript'];
759 757 }
760 758 return json;
761 759 };
762 760
763 761
764 762 Notebook.prototype.execute_selected_cell = function (options) {
765 763 // add_new: should a new cell be added if we are at the end of the nb
766 764 // terminal: execute in terminal mode, which stays in the current cell
767 765 default_options = {terminal: false, add_new: true}
768 766 $.extend(default_options, options)
769 767 var that = this;
770 768 var cell = that.selected_cell();
771 769 var cell_index = that.find_cell_index(cell);
772 770 if (cell instanceof IPython.CodeCell) {
773 771 cell.clear_output();
774 772 var code = cell.get_code();
775 773 var msg_id = that.kernel.execute(cell.get_code());
776 774 that.msg_cell_map[msg_id] = cell.cell_id;
777 775 } else if (cell instanceof IPython.HTMLCell) {
778 776 cell.render();
779 777 }
780 778 if (default_options.terminal) {
781 779 cell.clear_input();
782 780 } else {
783 781 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
784 782 that.insert_code_cell_after();
785 783 // If we are adding a new cell at the end, scroll down to show it.
786 784 that.scroll_to_bottom();
787 785 } else {
788 786 that.select(cell_index+1);
789 787 };
790 788 };
791 789 this.dirty = true;
792 790 };
793 791
794 792
795 793 Notebook.prototype.execute_all_cells = function () {
796 794 var ncells = this.ncells();
797 795 for (var i=0; i<ncells; i++) {
798 796 this.select(i);
799 797 this.execute_selected_cell({add_new:false});
800 798 };
801 799 this.scroll_to_bottom();
802 800 };
803 801
804 802
805 803 Notebook.prototype.complete_cell = function (cell, line, cursor_pos) {
806 804 var msg_id = this.kernel.complete(line, cursor_pos);
807 805 this.msg_cell_map[msg_id] = cell.cell_id;
808 806 };
809 807
810 808 // Persistance and loading
811 809
812 810
813 811 Notebook.prototype.fromJSON = function (data) {
814 812 var ncells = this.ncells();
815 813 for (var i=0; i<ncells; i++) {
816 814 // Always delete cell 0 as they get renumbered as they are deleted.
817 815 this.delete_cell(0);
818 816 };
819 817 // Save the metadata
820 818 this.metadata = data.metadata;
821 819 // Only handle 1 worksheet for now.
822 820 var worksheet = data.worksheets[0];
823 821 if (worksheet !== undefined) {
824 822 var new_cells = worksheet.cells;
825 823 ncells = new_cells.length;
826 824 var cell_data = null;
827 825 var new_cell = null;
828 826 for (var i=0; i<ncells; i++) {
829 827 cell_data = new_cells[i];
830 828 if (cell_data.cell_type == 'code') {
831 829 new_cell = this.insert_code_cell_after();
832 830 new_cell.fromJSON(cell_data);
833 831 } else if (cell_data.cell_type === 'html') {
834 832 new_cell = this.insert_html_cell_after();
835 833 new_cell.fromJSON(cell_data);
836 834 } else if (cell_data.cell_type === 'markdown') {
837 835 new_cell = this.insert_markdown_cell_after();
838 836 new_cell.fromJSON(cell_data);
839 837 };
840 838 };
841 839 };
842 840 };
843 841
844 842
845 843 Notebook.prototype.toJSON = function () {
846 844 var cells = this.cells();
847 845 var ncells = cells.length;
848 846 cell_array = new Array(ncells);
849 847 for (var i=0; i<ncells; i++) {
850 848 cell_array[i] = cells[i].toJSON();
851 849 };
852 850 data = {
853 851 // Only handle 1 worksheet for now.
854 852 worksheets : [{cells:cell_array}],
855 853 metadata : this.metadata
856 854 }
857 855 return data
858 856 };
859 857
860 858 Notebook.prototype.save_notebook = function () {
861 859 if (IPython.save_widget.test_notebook_name()) {
862 860 var notebook_id = IPython.save_widget.get_notebook_id();
863 861 var nbname = IPython.save_widget.get_notebook_name();
864 862 // We may want to move the name/id/nbformat logic inside toJSON?
865 863 var data = this.toJSON();
866 864 data.metadata.name = nbname;
867 865 data.nbformat = 2;
868 866 // We do the call with settings so we can set cache to false.
869 867 var settings = {
870 868 processData : false,
871 869 cache : false,
872 870 type : "PUT",
873 871 data : JSON.stringify(data),
874 872 headers : {'Content-Type': 'application/json'},
875 873 success : $.proxy(this.notebook_saved,this)
876 874 };
877 875 IPython.save_widget.status_saving();
878 876 $.ajax("/notebooks/" + notebook_id, settings);
879 877 };
880 878 };
881 879
882 880
883 881 Notebook.prototype.notebook_saved = function (data, status, xhr) {
884 882 this.dirty = false;
885 883 setTimeout($.proxy(IPython.save_widget.status_save,IPython.save_widget),500);
886 884 }
887 885
888 886
889 887 Notebook.prototype.load_notebook = function (callback) {
890 888 var that = this;
891 889 var notebook_id = IPython.save_widget.get_notebook_id();
892 890 // We do the call with settings so we can set cache to false.
893 891 var settings = {
894 892 processData : false,
895 893 cache : false,
896 894 type : "GET",
897 895 dataType : "json",
898 896 success : function (data, status, xhr) {
899 897 that.notebook_loaded(data, status, xhr);
900 898 if (callback !== undefined) {
901 899 callback();
902 900 };
903 901 }
904 902 };
905 903 IPython.save_widget.status_loading();
906 904 $.ajax("/notebooks/" + notebook_id, settings);
907 905 }
908 906
909 907
910 908 Notebook.prototype.notebook_loaded = function (data, status, xhr) {
911 909 this.fromJSON(data);
912 910 if (this.ncells() === 0) {
913 911 this.insert_code_cell_after();
914 912 };
915 913 IPython.save_widget.status_save();
916 914 IPython.save_widget.set_notebook_name(data.metadata.name);
917 915 this.start_kernel();
918 916 this.dirty = false;
919 917 // fromJSON always selects the last cell inserted. We need to wait
920 918 // until that is done before scrolling to the top.
921 919 setTimeout(function () {
922 920 IPython.notebook.select(0);
923 921 IPython.notebook.scroll_to_top();
924 922 }, 50);
925 923 };
926 924
927 925 IPython.Notebook = Notebook;
928 926
929 927 return IPython;
930 928
931 929 }(IPython));
932 930
General Comments 0
You need to be logged in to leave comments. Login now