##// END OF EJS Templates
htmlnotebook: Suppress cell boundary when publishing.
Stefan van der Walt -
Show More
@@ -1,832 +1,833 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 538 if (payload[i].text.trim() !== '') {
539 539 IPython.pager.clear();
540 540 IPython.pager.expand();
541 541 IPython.pager.append_text(payload[i].text);
542 542 }
543 543 } else if (payload[i].source === 'IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input') {
544 544 var index = this.find_cell_index(cell);
545 545 var new_cell = this.insert_code_cell_after(index);
546 546 new_cell.set_code(payload[i].text);
547 547 this.dirty = true;
548 548 }
549 549 };
550 550 };
551 551
552 552
553 553 Notebook.prototype.handle_iopub_reply = function (e) {
554 554 reply = $.parseJSON(e.data);
555 555 var content = reply.content;
556 556 // console.log(reply);
557 557 var msg_type = reply.header.msg_type;
558 558 var cell = this.cell_for_msg(reply.parent_header.msg_id);
559 559 var output_types = ['stream','display_data','pyout','pyerr'];
560 560 if (output_types.indexOf(msg_type) >= 0) {
561 561 this.handle_output(cell, msg_type, content);
562 562 } else if (msg_type === 'status') {
563 563 if (content.execution_state === 'busy') {
564 564 IPython.kernel_status_widget.status_busy();
565 565 } else if (content.execution_state === 'idle') {
566 566 IPython.kernel_status_widget.status_idle();
567 567 } else if (content.execution_state === 'dead') {
568 568 this.handle_status_dead();
569 569 };
570 570 }
571 571 };
572 572
573 573
574 574 Notebook.prototype.handle_status_dead = function () {
575 575 var that = this;
576 576 this.kernel.stop_channels();
577 577 var dialog = $('<div/>');
578 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.');
579 579 $(document).append(dialog);
580 580 dialog.dialog({
581 581 resizable: false,
582 582 modal: true,
583 583 title: "Dead kernel",
584 584 buttons : {
585 585 "Yes": function () {
586 586 that.start_kernel();
587 587 $(this).dialog('close');
588 588 },
589 589 "No": function () {
590 590 $(this).dialog('close');
591 591 }
592 592 }
593 593 });
594 594 };
595 595
596 596
597 597 Notebook.prototype.handle_output = function (cell, msg_type, content) {
598 598 var json = {};
599 599 json.output_type = msg_type;
600 600 if (msg_type === "stream") {
601 601 json.text = utils.fixConsole(content.data + '\n');
602 602 } else if (msg_type === "display_data") {
603 603 json = this.convert_mime_types(json, content.data);
604 604 } else if (msg_type === "pyout") {
605 605 json.prompt_number = content.execution_count;
606 606 json = this.convert_mime_types(json, content.data);
607 607 } else if (msg_type === "pyerr") {
608 608 json.ename = content.ename;
609 609 json.evalue = content.evalue;
610 610 var traceback = [];
611 611 for (var i=0; i<content.traceback.length; i++) {
612 612 traceback.push(utils.fixConsole(content.traceback[i]));
613 613 }
614 614 json.traceback = traceback;
615 615 };
616 616 cell.append_output(json);
617 617 this.dirty = true;
618 618 };
619 619
620 620
621 621 Notebook.prototype.convert_mime_types = function (json, data) {
622 622 if (data['text/plain'] !== undefined) {
623 623 json.text = utils.fixConsole(data['text/plain']);
624 624 };
625 625 if (data['text/html'] !== undefined) {
626 626 json.html = data['text/html'];
627 627 };
628 628 if (data['image/svg+xml'] !== undefined) {
629 629 json.svg = data['image/svg+xml'];
630 630 };
631 631 if (data['image/png'] !== undefined) {
632 632 json.png = data['image/png'];
633 633 };
634 634 if (data['image/jpeg'] !== undefined) {
635 635 json.jpeg = data['image/jpeg'];
636 636 };
637 637 if (data['text/latex'] !== undefined) {
638 638 json.latex = data['text/latex'];
639 639 };
640 640 if (data['application/json'] !== undefined) {
641 641 json.json = data['application/json'];
642 642 };
643 643 if (data['application/javascript'] !== undefined) {
644 644 json.javascript = data['application/javascript'];
645 645 }
646 646 return json;
647 647 };
648 648
649 649
650 650 Notebook.prototype.execute_selected_cell = function (options) {
651 651 // add_new: should a new cell be added if we are at the end of the nb
652 652 // terminal: execute in terminal mode, which stays in the current cell
653 653 default_options = {terminal: false, add_new: true}
654 654 $.extend(default_options, options)
655 655 var that = this;
656 656 var cell = that.selected_cell();
657 657 var cell_index = that.find_cell_index(cell);
658 658 if (cell instanceof IPython.CodeCell) {
659 659 cell.clear_output();
660 660 var code = cell.get_code();
661 661 var msg_id = that.kernel.execute(cell.get_code());
662 662 that.msg_cell_map[msg_id] = cell.cell_id;
663 663 } else if (cell instanceof IPython.HTMLCell) {
664 664 cell.render();
665 665 }
666 666 if (default_options.terminal) {
667 667 cell.clear_input();
668 668 } else {
669 669 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
670 670 that.insert_code_cell_after();
671 671 // If we are adding a new cell at the end, scroll down to show it.
672 672 that.scroll_to_bottom();
673 673 } else {
674 674 that.select(cell_index+1);
675 675 };
676 676 };
677 677 this.dirty = true;
678 678 };
679 679
680 680
681 681 Notebook.prototype.execute_all_cells = function () {
682 682 var ncells = this.ncells();
683 683 for (var i=0; i<ncells; i++) {
684 684 this.select(i);
685 685 this.execute_selected_cell({add_new:false});
686 686 };
687 687 this.scroll_to_bottom();
688 688 };
689 689
690 690
691 691 Notebook.prototype.complete_cell = function (cell, line, cursor_pos) {
692 692 var msg_id = this.kernel.complete(line, cursor_pos);
693 693 this.msg_cell_map[msg_id] = cell.cell_id;
694 694 };
695 695
696 696 // Persistance and loading
697 697
698 698
699 699 Notebook.prototype.fromJSON = function (data) {
700 700 var ncells = this.ncells();
701 701 for (var i=0; i<ncells; i++) {
702 702 // Always delete cell 0 as they get renumbered as they are deleted.
703 703 this.delete_cell(0);
704 704 };
705 705 // Only handle 1 worksheet for now.
706 706 var worksheet = data.worksheets[0];
707 707 if (worksheet !== undefined) {
708 708 var new_cells = worksheet.cells;
709 709 ncells = new_cells.length;
710 710 var cell_data = null;
711 711 var new_cell = null;
712 712 for (var i=0; i<ncells; i++) {
713 713 cell_data = new_cells[i];
714 714 if (cell_data.cell_type == 'code') {
715 715 new_cell = this.insert_code_cell_after();
716 716 new_cell.fromJSON(cell_data);
717 717 } else if (cell_data.cell_type === 'html') {
718 718 new_cell = this.insert_html_cell_after();
719 719 new_cell.fromJSON(cell_data);
720 720 } else if (cell_data.cell_type === 'markdown') {
721 721 new_cell = this.insert_markdown_cell_after();
722 722 new_cell.fromJSON(cell_data);
723 723 };
724 724 };
725 725 };
726 726 };
727 727
728 728
729 729 Notebook.prototype.toJSON = function () {
730 730 var cells = this.cells();
731 731 var ncells = cells.length;
732 732 cell_array = new Array(ncells);
733 733 for (var i=0; i<ncells; i++) {
734 734 cell_array[i] = cells[i].toJSON();
735 735 };
736 736 data = {
737 737 // Only handle 1 worksheet for now.
738 738 worksheets : [{cells:cell_array}]
739 739 }
740 740 return data
741 741 };
742 742
743 743 Notebook.prototype.save_notebook = function () {
744 744 if (IPython.save_widget.test_notebook_name()) {
745 745 var notebook_id = IPython.save_widget.get_notebook_id();
746 746 var nbname = IPython.save_widget.get_notebook_name();
747 747 // We may want to move the name/id/nbformat logic inside toJSON?
748 748 var data = this.toJSON();
749 749 data.name = nbname;
750 750 data.nbformat = 2;
751 751 // We do the call with settings so we can set cache to false.
752 752 var settings = {
753 753 processData : false,
754 754 cache : false,
755 755 type : "PUT",
756 756 data : JSON.stringify(data),
757 757 headers : {'Content-Type': 'application/json'},
758 758 success : $.proxy(this.notebook_saved,this)
759 759 };
760 760 IPython.save_widget.status_saving();
761 761 $.ajax("/notebooks/" + notebook_id, settings);
762 762 };
763 763 };
764 764
765 765 Notebook.prototype.publish_notebook = function () {
766 766 var w = window.open('', '_blank', 'scrollbars=1,menubar=1');
767 767 var html = '<html><head>' +
768 768 $('head').clone().html() +
769 769 '<style type="text/css">' +
770 770 '@media print { body { overflow: visible !important; } }' +
771 '.ui-widget-content { border: 0px; }' +
771 772 '</style>' +
772 773 '</head><body style="overflow: auto;">' +
773 774 $('#notebook').clone().html() +
774 775 '</body></html>';
775 776
776 777 w.document.open();
777 778 w.document.write(html);
778 779 w.document.close();
779 780
780 781 return false;
781 782 };
782 783
783 784 Notebook.prototype.notebook_saved = function (data, status, xhr) {
784 785 this.dirty = false;
785 786 setTimeout($.proxy(IPython.save_widget.status_save,IPython.save_widget),500);
786 787 }
787 788
788 789
789 790 Notebook.prototype.load_notebook = function (callback) {
790 791 var that = this;
791 792 var notebook_id = IPython.save_widget.get_notebook_id();
792 793 // We do the call with settings so we can set cache to false.
793 794 var settings = {
794 795 processData : false,
795 796 cache : false,
796 797 type : "GET",
797 798 dataType : "json",
798 799 success : function (data, status, xhr) {
799 800 that.notebook_loaded(data, status, xhr);
800 801 if (callback !== undefined) {
801 802 callback();
802 803 };
803 804 }
804 805 };
805 806 IPython.save_widget.status_loading();
806 807 $.ajax("/notebooks/" + notebook_id, settings);
807 808 }
808 809
809 810
810 811 Notebook.prototype.notebook_loaded = function (data, status, xhr) {
811 812 this.fromJSON(data);
812 813 if (this.ncells() === 0) {
813 814 this.insert_code_cell_after();
814 815 };
815 816 IPython.save_widget.status_save();
816 817 IPython.save_widget.set_notebook_name(data.name);
817 818 this.start_kernel();
818 819 this.dirty = false;
819 820 // fromJSON always selects the last cell inserted. We need to wait
820 821 // until that is done before scrolling to the top.
821 822 setTimeout(function () {
822 823 IPython.notebook.select(0);
823 824 IPython.notebook.scroll_to_top();
824 825 }, 50);
825 826 };
826 827
827 828 IPython.Notebook = Notebook;
828 829
829 830 return IPython;
830 831
831 832 }(IPython));
832 833
General Comments 0
You need to be logged in to leave comments. Login now