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