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