##// END OF EJS Templates
Add comment re: quickhelp key.
David Warde-Farley -
Show More
@@ -1,1362 +1,1363
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 var key = IPython.utils.keycodes;
16 16
17 17 var Notebook = function (selector) {
18 18 this.read_only = IPython.read_only;
19 19 this.element = $(selector);
20 20 this.element.scroll();
21 21 this.element.data("notebook", this);
22 22 this.next_prompt_number = 1;
23 23 this.kernel = null;
24 24 this.clipboard = null;
25 25 this.undelete_backup = null;
26 26 this.undelete_index = null;
27 27 this.undelete_below = false;
28 28 this.paste_enabled = false;
29 29 this.dirty = false;
30 30 this.metadata = {};
31 31 // single worksheet for now
32 32 this.worksheet_metadata = {};
33 33 this.control_key_active = false;
34 34 this.notebook_id = null;
35 35 this.notebook_name = null;
36 36 this.notebook_name_blacklist_re = /[\/\\:]/;
37 37 this.nbformat = 3 // Increment this when changing the nbformat
38 38 this.nbformat_minor = 0 // Increment this when changing the nbformat
39 39 this.style();
40 40 this.create_elements();
41 41 this.bind_events();
42 42 };
43 43
44 44
45 45 Notebook.prototype.style = function () {
46 46 $('div#notebook').addClass('border-box-sizing');
47 47 };
48 48
49 49
50 50 Notebook.prototype.create_elements = function () {
51 51 // We add this end_space div to the end of the notebook div to:
52 52 // i) provide a margin between the last cell and the end of the notebook
53 53 // ii) to prevent the div from scrolling up when the last cell is being
54 54 // edited, but is too low on the page, which browsers will do automatically.
55 55 var that = this;
56 56 var end_space = $('<div/>').addClass('end_space').height("30%");
57 57 end_space.dblclick(function (e) {
58 58 if (that.read_only) return;
59 59 var ncells = that.ncells();
60 60 that.insert_cell_below('code',ncells-1);
61 61 });
62 62 this.element.append(end_space);
63 63 $('div#notebook').addClass('border-box-sizing');
64 64 };
65 65
66 66
67 67 Notebook.prototype.bind_events = function () {
68 68 var that = this;
69 69
70 70 $([IPython.events]).on('set_next_input.Notebook', function (event, data) {
71 71 var index = that.find_cell_index(data.cell);
72 72 var new_cell = that.insert_cell_below('code',index);
73 73 new_cell.set_text(data.text);
74 74 that.dirty = true;
75 75 });
76 76
77 77 $([IPython.events]).on('set_dirty.Notebook', function (event, data) {
78 78 that.dirty = data.value;
79 79 });
80 80
81 81 $([IPython.events]).on('select.Cell', function (event, data) {
82 82 var index = that.find_cell_index(data.cell);
83 83 that.select(index);
84 84 });
85 85
86 86
87 87 $(document).keydown(function (event) {
88 88 // console.log(event);
89 89 if (that.read_only) return true;
90 90
91 91 // Save (CTRL+S) or (AppleKey+S)
92 92 //metaKey = applekey on mac
93 93 if ((event.ctrlKey || event.metaKey) && event.keyCode==83) {
94 94 that.save_notebook();
95 95 event.preventDefault();
96 96 return false;
97 97 } else if (event.which === key.ESC) {
98 98 // Intercept escape at highest level to avoid closing
99 99 // websocket connection with firefox
100 100 event.preventDefault();
101 101 } else if (event.which === key.SHIFT) {
102 102 // ignore shift keydown
103 103 return true;
104 104 }
105 105 if (event.which === key.UPARROW && !event.shiftKey) {
106 106 var cell = that.get_selected_cell();
107 107 if (cell.at_top()) {
108 108 event.preventDefault();
109 109 that.select_prev();
110 110 };
111 111 } else if (event.which === key.DOWNARROW && !event.shiftKey) {
112 112 var cell = that.get_selected_cell();
113 113 if (cell.at_bottom()) {
114 114 event.preventDefault();
115 115 that.select_next();
116 116 };
117 117 } else if (event.which === key.ENTER && event.shiftKey) {
118 118 that.execute_selected_cell();
119 119 return false;
120 120 } else if (event.which === key.ENTER && event.altKey) {
121 121 // Execute code cell, and insert new in place
122 122 that.execute_selected_cell();
123 123 // Only insert a new cell, if we ended up in an already populated cell
124 124 if (/\S/.test(that.get_selected_cell().get_text()) == true) {
125 125 that.insert_cell_above('code');
126 126 }
127 127 return false;
128 128 } else if (event.which === key.ENTER && event.ctrlKey) {
129 129 that.execute_selected_cell({terminal:true});
130 130 return false;
131 131 } else if (event.which === 77 && event.ctrlKey && that.control_key_active == false) {
132 132 that.control_key_active = true;
133 133 return false;
134 134 } else if (event.which === 88 && that.control_key_active) {
135 135 // Cut selected cell = x
136 136 that.cut_cell();
137 137 that.control_key_active = false;
138 138 return false;
139 139 } else if (event.which === 67 && that.control_key_active) {
140 140 // Copy selected cell = c
141 141 that.copy_cell();
142 142 that.control_key_active = false;
143 143 return false;
144 144 } else if (event.which === 86 && that.control_key_active) {
145 145 // Paste selected cell = v
146 146 that.paste_cell();
147 147 that.control_key_active = false;
148 148 return false;
149 149 } else if (event.which === 68 && that.control_key_active) {
150 150 // Delete selected cell = d
151 151 that.delete_cell();
152 152 that.control_key_active = false;
153 153 return false;
154 154 } else if (event.which === 65 && that.control_key_active) {
155 155 // Insert code cell above selected = a
156 156 that.insert_cell_above('code');
157 157 that.control_key_active = false;
158 158 return false;
159 159 } else if (event.which === 66 && that.control_key_active) {
160 160 // Insert code cell below selected = b
161 161 that.insert_cell_below('code');
162 162 that.control_key_active = false;
163 163 return false;
164 164 } else if (event.which === 89 && that.control_key_active) {
165 165 // To code = y
166 166 that.to_code();
167 167 that.control_key_active = false;
168 168 return false;
169 169 } else if (event.which === 77 && that.control_key_active) {
170 170 // To markdown = m
171 171 that.to_markdown();
172 172 that.control_key_active = false;
173 173 return false;
174 174 } else if (event.which === 84 && that.control_key_active) {
175 175 // To Raw = t
176 176 that.to_raw();
177 177 that.control_key_active = false;
178 178 return false;
179 179 } else if (event.which === 49 && that.control_key_active) {
180 180 // To Heading 1 = 1
181 181 that.to_heading(undefined, 1);
182 182 that.control_key_active = false;
183 183 return false;
184 184 } else if (event.which === 50 && that.control_key_active) {
185 185 // To Heading 2 = 2
186 186 that.to_heading(undefined, 2);
187 187 that.control_key_active = false;
188 188 return false;
189 189 } else if (event.which === 51 && that.control_key_active) {
190 190 // To Heading 3 = 3
191 191 that.to_heading(undefined, 3);
192 192 that.control_key_active = false;
193 193 return false;
194 194 } else if (event.which === 52 && that.control_key_active) {
195 195 // To Heading 4 = 4
196 196 that.to_heading(undefined, 4);
197 197 that.control_key_active = false;
198 198 return false;
199 199 } else if (event.which === 53 && that.control_key_active) {
200 200 // To Heading 5 = 5
201 201 that.to_heading(undefined, 5);
202 202 that.control_key_active = false;
203 203 return false;
204 204 } else if (event.which === 54 && that.control_key_active) {
205 205 // To Heading 6 = 6
206 206 that.to_heading(undefined, 6);
207 207 that.control_key_active = false;
208 208 return false;
209 209 } else if (event.which === 79 && that.control_key_active) {
210 210 // Toggle output = o
211 211 if (event.shiftKey){
212 212 that.toggle_output_scroll();
213 213 } else {
214 214 that.toggle_output();
215 215 }
216 216 that.control_key_active = false;
217 217 return false;
218 218 } else if (event.which === 83 && that.control_key_active) {
219 219 // Save notebook = s
220 220 that.save_notebook();
221 221 that.control_key_active = false;
222 222 return false;
223 223 } else if (event.which === 74 && that.control_key_active) {
224 224 // Move cell down = j
225 225 that.move_cell_down();
226 226 that.control_key_active = false;
227 227 return false;
228 228 } else if (event.which === 75 && that.control_key_active) {
229 229 // Move cell up = k
230 230 that.move_cell_up();
231 231 that.control_key_active = false;
232 232 return false;
233 233 } else if (event.which === 80 && that.control_key_active) {
234 234 // Select previous = p
235 235 that.select_prev();
236 236 that.control_key_active = false;
237 237 return false;
238 238 } else if (event.which === 78 && that.control_key_active) {
239 239 // Select next = n
240 240 that.select_next();
241 241 that.control_key_active = false;
242 242 return false;
243 243 } else if (event.which === 76 && that.control_key_active) {
244 244 // Toggle line numbers = l
245 245 that.cell_toggle_line_numbers();
246 246 that.control_key_active = false;
247 247 return false;
248 248 } else if (event.which === 73 && that.control_key_active) {
249 249 // Interrupt kernel = i
250 250 that.kernel.interrupt();
251 251 that.control_key_active = false;
252 252 return false;
253 253 } else if (event.which === 190 && that.control_key_active) {
254 254 // Restart kernel = . # matches qt console
255 255 that.restart_kernel();
256 256 that.control_key_active = false;
257 257 return false;
258 258 } else if (event.which === 72 && that.control_key_active) {
259 259 // Show keyboard shortcuts = h
260 260 IPython.quick_help.show_keyboard_shortcuts();
261 261 that.control_key_active = false;
262 262 return false;
263 263 } else if (event.which === 90 && that.control_key_active) {
264 // Undo last cell delete = z
264 265 that.undelete();
265 266 that.control_key_active = false;
266 267 return false;
267 268 } else if (that.control_key_active) {
268 269 that.control_key_active = false;
269 270 return true;
270 271 };
271 272 return true;
272 273 });
273 274
274 275 var collapse_time = function(time){
275 276 var app_height = $('div#main_app').height(); // content height
276 277 var splitter_height = $('div#pager_splitter').outerHeight(true);
277 278 var new_height = app_height - splitter_height;
278 279 that.element.animate({height : new_height + 'px'}, time);
279 280 }
280 281
281 282 this.element.bind('collapse_pager', function (event,extrap) {
282 283 time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast';
283 284 collapse_time(time);
284 285 });
285 286
286 287 var expand_time = function(time) {
287 288 var app_height = $('div#main_app').height(); // content height
288 289 var splitter_height = $('div#pager_splitter').outerHeight(true);
289 290 var pager_height = $('div#pager').outerHeight(true);
290 291 var new_height = app_height - pager_height - splitter_height;
291 292 that.element.animate({height : new_height + 'px'}, time);
292 293 }
293 294
294 295 this.element.bind('expand_pager', function (event, extrap) {
295 296 time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast';
296 297 expand_time(time);
297 298 });
298 299
299 300 $(window).bind('beforeunload', function () {
300 301 // TODO: Make killing the kernel configurable.
301 302 var kill_kernel = false;
302 303 if (kill_kernel) {
303 304 that.kernel.kill();
304 305 }
305 306 if (that.dirty && ! that.read_only) {
306 307 return "You have unsaved changes that will be lost if you leave this page.";
307 308 };
308 309 // Null is the *only* return value that will make the browser not
309 310 // pop up the "don't leave" dialog.
310 311 return null;
311 312 });
312 313 };
313 314
314 315 Notebook.prototype.scroll_to_cell = function (cell_number, time) {
315 316 var cells = this.get_cells();
316 317 var time = time || 0;
317 318 cell_number = Math.min(cells.length-1,cell_number);
318 319 cell_number = Math.max(0 ,cell_number);
319 320 scroll_value = cells[cell_number].element.position().top-cells[0].element.position().top ;
320 321 this.element.animate({scrollTop:scroll_value}, time);
321 322 return scroll_value;
322 323 };
323 324
324 325
325 326 Notebook.prototype.scroll_to_bottom = function () {
326 327 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
327 328 };
328 329
329 330
330 331 Notebook.prototype.scroll_to_top = function () {
331 332 this.element.animate({scrollTop:0}, 0);
332 333 };
333 334
334 335
335 336 // Cell indexing, retrieval, etc.
336 337
337 338 Notebook.prototype.get_cell_elements = function () {
338 339 return this.element.children("div.cell");
339 340 };
340 341
341 342
342 343 Notebook.prototype.get_cell_element = function (index) {
343 344 var result = null;
344 345 var e = this.get_cell_elements().eq(index);
345 346 if (e.length !== 0) {
346 347 result = e;
347 348 }
348 349 return result;
349 350 };
350 351
351 352
352 353 Notebook.prototype.ncells = function (cell) {
353 354 return this.get_cell_elements().length;
354 355 };
355 356
356 357
357 358 // TODO: we are often calling cells as cells()[i], which we should optimize
358 359 // to cells(i) or a new method.
359 360 Notebook.prototype.get_cells = function () {
360 361 return this.get_cell_elements().toArray().map(function (e) {
361 362 return $(e).data("cell");
362 363 });
363 364 };
364 365
365 366
366 367 Notebook.prototype.get_cell = function (index) {
367 368 var result = null;
368 369 var ce = this.get_cell_element(index);
369 370 if (ce !== null) {
370 371 result = ce.data('cell');
371 372 }
372 373 return result;
373 374 }
374 375
375 376
376 377 Notebook.prototype.get_next_cell = function (cell) {
377 378 var result = null;
378 379 var index = this.find_cell_index(cell);
379 380 if (index !== null && index < this.ncells()) {
380 381 result = this.get_cell(index+1);
381 382 }
382 383 return result;
383 384 }
384 385
385 386
386 387 Notebook.prototype.get_prev_cell = function (cell) {
387 388 var result = null;
388 389 var index = this.find_cell_index(cell);
389 390 if (index !== null && index > 1) {
390 391 result = this.get_cell(index-1);
391 392 }
392 393 return result;
393 394 }
394 395
395 396 Notebook.prototype.find_cell_index = function (cell) {
396 397 var result = null;
397 398 this.get_cell_elements().filter(function (index) {
398 399 if ($(this).data("cell") === cell) {
399 400 result = index;
400 401 };
401 402 });
402 403 return result;
403 404 };
404 405
405 406
406 407 Notebook.prototype.index_or_selected = function (index) {
407 408 var i;
408 409 if (index === undefined || index === null) {
409 410 i = this.get_selected_index();
410 411 if (i === null) {
411 412 i = 0;
412 413 }
413 414 } else {
414 415 i = index;
415 416 }
416 417 return i;
417 418 };
418 419
419 420
420 421 Notebook.prototype.get_selected_cell = function () {
421 422 var index = this.get_selected_index();
422 423 return this.get_cell(index);
423 424 };
424 425
425 426
426 427 Notebook.prototype.is_valid_cell_index = function (index) {
427 428 if (index !== null && index >= 0 && index < this.ncells()) {
428 429 return true;
429 430 } else {
430 431 return false;
431 432 };
432 433 }
433 434
434 435 Notebook.prototype.get_selected_index = function () {
435 436 var result = null;
436 437 this.get_cell_elements().filter(function (index) {
437 438 if ($(this).data("cell").selected === true) {
438 439 result = index;
439 440 };
440 441 });
441 442 return result;
442 443 };
443 444
444 445
445 446 // Cell selection.
446 447
447 448 Notebook.prototype.select = function (index) {
448 449 if (index !== undefined && index >= 0 && index < this.ncells()) {
449 450 sindex = this.get_selected_index()
450 451 if (sindex !== null && index !== sindex) {
451 452 this.get_cell(sindex).unselect();
452 453 };
453 454 var cell = this.get_cell(index)
454 455 cell.select();
455 456 if (cell.cell_type === 'heading') {
456 457 $([IPython.events]).trigger('selected_cell_type_changed.Notebook',
457 458 {'cell_type':cell.cell_type,level:cell.level}
458 459 );
459 460 } else {
460 461 $([IPython.events]).trigger('selected_cell_type_changed.Notebook',
461 462 {'cell_type':cell.cell_type}
462 463 );
463 464 };
464 465 };
465 466 return this;
466 467 };
467 468
468 469
469 470 Notebook.prototype.select_next = function () {
470 471 var index = this.get_selected_index();
471 472 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
472 473 this.select(index+1);
473 474 };
474 475 return this;
475 476 };
476 477
477 478
478 479 Notebook.prototype.select_prev = function () {
479 480 var index = this.get_selected_index();
480 481 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
481 482 this.select(index-1);
482 483 };
483 484 return this;
484 485 };
485 486
486 487
487 488 // Cell movement
488 489
489 490 Notebook.prototype.move_cell_up = function (index) {
490 491 var i = this.index_or_selected();
491 492 if (i !== null && i < this.ncells() && i > 0) {
492 493 var pivot = this.get_cell_element(i-1);
493 494 var tomove = this.get_cell_element(i);
494 495 if (pivot !== null && tomove !== null) {
495 496 tomove.detach();
496 497 pivot.before(tomove);
497 498 this.select(i-1);
498 499 };
499 500 };
500 501 this.dirty = true;
501 502 return this;
502 503 };
503 504
504 505
505 506 Notebook.prototype.move_cell_down = function (index) {
506 507 var i = this.index_or_selected();
507 508 if (i !== null && i < (this.ncells()-1) && i >= 0) {
508 509 var pivot = this.get_cell_element(i+1);
509 510 var tomove = this.get_cell_element(i);
510 511 if (pivot !== null && tomove !== null) {
511 512 tomove.detach();
512 513 pivot.after(tomove);
513 514 this.select(i+1);
514 515 };
515 516 };
516 517 this.dirty = true;
517 518 return this;
518 519 };
519 520
520 521
521 522 Notebook.prototype.sort_cells = function () {
522 523 // This is not working right now. Calling this will actually crash
523 524 // the browser. I think there is an infinite loop in here...
524 525 var ncells = this.ncells();
525 526 var sindex = this.get_selected_index();
526 527 var swapped;
527 528 do {
528 529 swapped = false;
529 530 for (var i=1; i<ncells; i++) {
530 531 current = this.get_cell(i);
531 532 previous = this.get_cell(i-1);
532 533 if (previous.input_prompt_number > current.input_prompt_number) {
533 534 this.move_cell_up(i);
534 535 swapped = true;
535 536 };
536 537 };
537 538 } while (swapped);
538 539 this.select(sindex);
539 540 return this;
540 541 };
541 542
542 543 // Insertion, deletion.
543 544
544 545 Notebook.prototype.delete_cell = function (index) {
545 546 var i = this.index_or_selected(index);
546 547 var cell = this.get_selected_cell();
547 548 this.undelete_backup = cell.toJSON();
548 549 if (this.is_valid_cell_index(i)) {
549 550 var ce = this.get_cell_element(i);
550 551 ce.remove();
551 552 if (i === (this.ncells())) {
552 553 this.select(i-1);
553 554 this.undelete_index = i - 1;
554 555 this.undelete_below = true;
555 556 } else {
556 557 this.select(i);
557 558 this.undelete_index = i;
558 559 this.undelete_below = false;
559 560 };
560 561 this.dirty = true;
561 562 };
562 563 return this;
563 564 };
564 565
565 566
566 567 Notebook.prototype.insert_cell_at_bottom = function (type){
567 568 var len = this.ncells();
568 569 return this.insert_cell_below(type,len-1);
569 570 }
570 571
571 572 Notebook.prototype.insert_cell_below = function (type, index) {
572 573 // type = ('code','html','markdown')
573 574 // index = cell index or undefined to insert below selected
574 575 index = this.index_or_selected(index);
575 576 var cell = null;
576 577 if (this.ncells() === 0 || this.is_valid_cell_index(index)) {
577 578 if (type === 'code') {
578 579 cell = new IPython.CodeCell(this.kernel);
579 580 cell.set_input_prompt();
580 581 } else if (type === 'markdown') {
581 582 cell = new IPython.MarkdownCell();
582 583 } else if (type === 'html') {
583 584 cell = new IPython.HTMLCell();
584 585 } else if (type === 'raw') {
585 586 cell = new IPython.RawCell();
586 587 } else if (type === 'heading') {
587 588 cell = new IPython.HeadingCell();
588 589 };
589 590 if (cell !== null) {
590 591 if (this.ncells() === 0) {
591 592 this.element.find('div.end_space').before(cell.element);
592 593 } else if (this.is_valid_cell_index(index)) {
593 594 this.get_cell_element(index).after(cell.element);
594 595 };
595 596 cell.render();
596 597 this.select(this.find_cell_index(cell));
597 598 this.dirty = true;
598 599 return cell;
599 600 };
600 601 };
601 602 return cell;
602 603 };
603 604
604 605
605 606 Notebook.prototype.insert_cell_above = function (type, index) {
606 607 // type = ('code','html','markdown')
607 608 // index = cell index or undefined to insert above selected
608 609 index = this.index_or_selected(index);
609 610 var cell = null;
610 611 if (this.ncells() === 0 || this.is_valid_cell_index(index)) {
611 612 if (type === 'code') {
612 613 cell = new IPython.CodeCell(this.kernel);
613 614 cell.set_input_prompt();
614 615 } else if (type === 'markdown') {
615 616 cell = new IPython.MarkdownCell();
616 617 } else if (type === 'html') {
617 618 cell = new IPython.HTMLCell();
618 619 } else if (type === 'raw') {
619 620 cell = new IPython.RawCell();
620 621 } else if (type === 'heading') {
621 622 cell = new IPython.HeadingCell();
622 623 };
623 624 if (cell !== null) {
624 625 if (this.ncells() === 0) {
625 626 this.element.find('div.end_space').before(cell.element);
626 627 } else if (this.is_valid_cell_index(index)) {
627 628 this.get_cell_element(index).before(cell.element);
628 629 };
629 630 cell.render();
630 631 this.select(this.find_cell_index(cell));
631 632 this.dirty = true;
632 633 return cell;
633 634 };
634 635 };
635 636 return cell;
636 637 };
637 638
638 639
639 640 Notebook.prototype.to_code = function (index) {
640 641 var i = this.index_or_selected(index);
641 642 if (this.is_valid_cell_index(i)) {
642 643 var source_element = this.get_cell_element(i);
643 644 var source_cell = source_element.data("cell");
644 645 if (!(source_cell instanceof IPython.CodeCell)) {
645 646 target_cell = this.insert_cell_below('code',i);
646 647 var text = source_cell.get_text();
647 648 if (text === source_cell.placeholder) {
648 649 text = '';
649 650 }
650 651 target_cell.set_text(text);
651 652 // make this value the starting point, so that we can only undo
652 653 // to this state, instead of a blank cell
653 654 target_cell.code_mirror.clearHistory();
654 655 source_element.remove();
655 656 this.dirty = true;
656 657 };
657 658 };
658 659 };
659 660
660 661
661 662 Notebook.prototype.to_markdown = function (index) {
662 663 var i = this.index_or_selected(index);
663 664 if (this.is_valid_cell_index(i)) {
664 665 var source_element = this.get_cell_element(i);
665 666 var source_cell = source_element.data("cell");
666 667 if (!(source_cell instanceof IPython.MarkdownCell)) {
667 668 target_cell = this.insert_cell_below('markdown',i);
668 669 var text = source_cell.get_text();
669 670 if (text === source_cell.placeholder) {
670 671 text = '';
671 672 };
672 673 // The edit must come before the set_text.
673 674 target_cell.edit();
674 675 target_cell.set_text(text);
675 676 // make this value the starting point, so that we can only undo
676 677 // to this state, instead of a blank cell
677 678 target_cell.code_mirror.clearHistory();
678 679 source_element.remove();
679 680 this.dirty = true;
680 681 };
681 682 };
682 683 };
683 684
684 685
685 686 Notebook.prototype.to_html = function (index) {
686 687 var i = this.index_or_selected(index);
687 688 if (this.is_valid_cell_index(i)) {
688 689 var source_element = this.get_cell_element(i);
689 690 var source_cell = source_element.data("cell");
690 691 var target_cell = null;
691 692 if (!(source_cell instanceof IPython.HTMLCell)) {
692 693 target_cell = this.insert_cell_below('html',i);
693 694 var text = source_cell.get_text();
694 695 if (text === source_cell.placeholder) {
695 696 text = '';
696 697 };
697 698 // The edit must come before the set_text.
698 699 target_cell.edit();
699 700 target_cell.set_text(text);
700 701 // make this value the starting point, so that we can only undo
701 702 // to this state, instead of a blank cell
702 703 target_cell.code_mirror.clearHistory();
703 704 source_element.remove();
704 705 this.dirty = true;
705 706 };
706 707 };
707 708 };
708 709
709 710
710 711 Notebook.prototype.to_raw = function (index) {
711 712 var i = this.index_or_selected(index);
712 713 if (this.is_valid_cell_index(i)) {
713 714 var source_element = this.get_cell_element(i);
714 715 var source_cell = source_element.data("cell");
715 716 var target_cell = null;
716 717 if (!(source_cell instanceof IPython.RawCell)) {
717 718 target_cell = this.insert_cell_below('raw',i);
718 719 var text = source_cell.get_text();
719 720 if (text === source_cell.placeholder) {
720 721 text = '';
721 722 };
722 723 // The edit must come before the set_text.
723 724 target_cell.edit();
724 725 target_cell.set_text(text);
725 726 // make this value the starting point, so that we can only undo
726 727 // to this state, instead of a blank cell
727 728 target_cell.code_mirror.clearHistory();
728 729 source_element.remove();
729 730 this.dirty = true;
730 731 };
731 732 };
732 733 };
733 734
734 735
735 736 Notebook.prototype.to_heading = function (index, level) {
736 737 level = level || 1;
737 738 var i = this.index_or_selected(index);
738 739 if (this.is_valid_cell_index(i)) {
739 740 var source_element = this.get_cell_element(i);
740 741 var source_cell = source_element.data("cell");
741 742 var target_cell = null;
742 743 if (source_cell instanceof IPython.HeadingCell) {
743 744 source_cell.set_level(level);
744 745 } else {
745 746 target_cell = this.insert_cell_below('heading',i);
746 747 var text = source_cell.get_text();
747 748 if (text === source_cell.placeholder) {
748 749 text = '';
749 750 };
750 751 // The edit must come before the set_text.
751 752 target_cell.set_level(level);
752 753 target_cell.edit();
753 754 target_cell.set_text(text);
754 755 // make this value the starting point, so that we can only undo
755 756 // to this state, instead of a blank cell
756 757 target_cell.code_mirror.clearHistory();
757 758 source_element.remove();
758 759 this.dirty = true;
759 760 };
760 761 $([IPython.events]).trigger('selected_cell_type_changed.Notebook',
761 762 {'cell_type':'heading',level:level}
762 763 );
763 764 };
764 765 };
765 766
766 767
767 768 // Cut/Copy/Paste
768 769
769 770 Notebook.prototype.enable_paste = function () {
770 771 var that = this;
771 772 if (!this.paste_enabled) {
772 773 $('#paste_cell').removeClass('ui-state-disabled')
773 774 .on('click', function () {that.paste_cell();});
774 775 $('#paste_cell_above').removeClass('ui-state-disabled')
775 776 .on('click', function () {that.paste_cell_above();});
776 777 $('#paste_cell_below').removeClass('ui-state-disabled')
777 778 .on('click', function () {that.paste_cell_below();});
778 779 this.paste_enabled = true;
779 780 };
780 781 };
781 782
782 783
783 784 Notebook.prototype.disable_paste = function () {
784 785 if (this.paste_enabled) {
785 786 $('#paste_cell').addClass('ui-state-disabled').off('click');
786 787 $('#paste_cell_above').addClass('ui-state-disabled').off('click');
787 788 $('#paste_cell_below').addClass('ui-state-disabled').off('click');
788 789 this.paste_enabled = false;
789 790 };
790 791 };
791 792
792 793
793 794 Notebook.prototype.cut_cell = function () {
794 795 this.copy_cell();
795 796 this.delete_cell();
796 797 }
797 798
798 799 Notebook.prototype.copy_cell = function () {
799 800 var cell = this.get_selected_cell();
800 801 this.clipboard = cell.toJSON();
801 802 this.enable_paste();
802 803 };
803 804
804 805
805 806 Notebook.prototype.paste_cell = function () {
806 807 if (this.clipboard !== null && this.paste_enabled) {
807 808 var cell_data = this.clipboard;
808 809 var new_cell = this.insert_cell_above(cell_data.cell_type);
809 810 new_cell.fromJSON(cell_data);
810 811 old_cell = this.get_next_cell(new_cell);
811 812 this.delete_cell(this.find_cell_index(old_cell));
812 813 this.select(this.find_cell_index(new_cell));
813 814 };
814 815 };
815 816
816 817
817 818 Notebook.prototype.paste_cell_above = function () {
818 819 if (this.clipboard !== null && this.paste_enabled) {
819 820 var cell_data = this.clipboard;
820 821 var new_cell = this.insert_cell_above(cell_data.cell_type);
821 822 new_cell.fromJSON(cell_data);
822 823 };
823 824 };
824 825
825 826
826 827 Notebook.prototype.paste_cell_below = function () {
827 828 if (this.clipboard !== null && this.paste_enabled) {
828 829 var cell_data = this.clipboard;
829 830 var new_cell = this.insert_cell_below(cell_data.cell_type);
830 831 new_cell.fromJSON(cell_data);
831 832 };
832 833 };
833 834
834 835 // Cell undelete
835 836
836 837 Notebook.prototype.undelete = function() {
837 838 if (this.undelete_backup !== null && this.undelete_index !== null) {
838 839 var current_index = this.get_selected_index();
839 840 if (this.undelete_index < current_index) {
840 841 current_index = current_index + 1;
841 842 }
842 843 if (this.undelete_index >= this.ncells()) {
843 844 this.select(this.ncells() - 1);
844 845 }
845 846 else {
846 847 this.select(this.undelete_index);
847 848 }
848 849 var cell_data = this.undelete_backup;
849 850 var new_cell = null;
850 851 if (this.undelete_below) {
851 852 new_cell = this.insert_cell_below(cell_data.cell_type);
852 853 } else {
853 854 new_cell = this.insert_cell_above(cell_data.cell_type);
854 855 }
855 856 new_cell.fromJSON(cell_data);
856 857 this.select(current_index);
857 858 this.undelete_backup = null;
858 859 this.undelete_index = null;
859 860 }
860 861 }
861 862
862 863 // Split/merge
863 864
864 865 Notebook.prototype.split_cell = function () {
865 866 // Todo: implement spliting for other cell types.
866 867 var cell = this.get_selected_cell();
867 868 if (cell.is_splittable()) {
868 869 texta = cell.get_pre_cursor();
869 870 textb = cell.get_post_cursor();
870 871 if (cell instanceof IPython.CodeCell) {
871 872 cell.set_text(texta);
872 873 var new_cell = this.insert_cell_below('code');
873 874 new_cell.set_text(textb);
874 875 } else if (cell instanceof IPython.MarkdownCell) {
875 876 cell.set_text(texta);
876 877 cell.render();
877 878 var new_cell = this.insert_cell_below('markdown');
878 879 new_cell.edit(); // editor must be visible to call set_text
879 880 new_cell.set_text(textb);
880 881 new_cell.render();
881 882 } else if (cell instanceof IPython.HTMLCell) {
882 883 cell.set_text(texta);
883 884 cell.render();
884 885 var new_cell = this.insert_cell_below('html');
885 886 new_cell.edit(); // editor must be visible to call set_text
886 887 new_cell.set_text(textb);
887 888 new_cell.render();
888 889 };
889 890 };
890 891 };
891 892
892 893
893 894 Notebook.prototype.merge_cell_above = function () {
894 895 var index = this.get_selected_index();
895 896 var cell = this.get_cell(index);
896 897 if (index > 0) {
897 898 upper_cell = this.get_cell(index-1);
898 899 upper_text = upper_cell.get_text();
899 900 text = cell.get_text();
900 901 if (cell instanceof IPython.CodeCell) {
901 902 cell.set_text(upper_text+'\n'+text);
902 903 } else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) {
903 904 cell.edit();
904 905 cell.set_text(upper_text+'\n'+text);
905 906 cell.render();
906 907 };
907 908 this.delete_cell(index-1);
908 909 this.select(this.find_cell_index(cell));
909 910 };
910 911 };
911 912
912 913
913 914 Notebook.prototype.merge_cell_below = function () {
914 915 var index = this.get_selected_index();
915 916 var cell = this.get_cell(index);
916 917 if (index < this.ncells()-1) {
917 918 lower_cell = this.get_cell(index+1);
918 919 lower_text = lower_cell.get_text();
919 920 text = cell.get_text();
920 921 if (cell instanceof IPython.CodeCell) {
921 922 cell.set_text(text+'\n'+lower_text);
922 923 } else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) {
923 924 cell.edit();
924 925 cell.set_text(text+'\n'+lower_text);
925 926 cell.render();
926 927 };
927 928 this.delete_cell(index+1);
928 929 this.select(this.find_cell_index(cell));
929 930 };
930 931 };
931 932
932 933
933 934 // Cell collapsing and output clearing
934 935
935 936 Notebook.prototype.collapse = function (index) {
936 937 var i = this.index_or_selected(index);
937 938 this.get_cell(i).collapse();
938 939 this.dirty = true;
939 940 };
940 941
941 942
942 943 Notebook.prototype.expand = function (index) {
943 944 var i = this.index_or_selected(index);
944 945 this.get_cell(i).expand();
945 946 this.dirty = true;
946 947 };
947 948
948 949
949 950 Notebook.prototype.toggle_output = function (index) {
950 951 var i = this.index_or_selected(index);
951 952 this.get_cell(i).toggle_output();
952 953 this.dirty = true;
953 954 };
954 955
955 956
956 957 Notebook.prototype.toggle_output_scroll = function (index) {
957 958 var i = this.index_or_selected(index);
958 959 this.get_cell(i).toggle_output_scroll();
959 960 };
960 961
961 962
962 963 Notebook.prototype.collapse_all_output = function () {
963 964 var ncells = this.ncells();
964 965 var cells = this.get_cells();
965 966 for (var i=0; i<ncells; i++) {
966 967 if (cells[i] instanceof IPython.CodeCell) {
967 968 cells[i].output_area.collapse();
968 969 }
969 970 };
970 971 // this should not be set if the `collapse` key is removed from nbformat
971 972 this.dirty = true;
972 973 };
973 974
974 975
975 976 Notebook.prototype.scroll_all_output = function () {
976 977 var ncells = this.ncells();
977 978 var cells = this.get_cells();
978 979 for (var i=0; i<ncells; i++) {
979 980 if (cells[i] instanceof IPython.CodeCell) {
980 981 cells[i].output_area.expand();
981 982 cells[i].output_area.scroll_if_long(20);
982 983 }
983 984 };
984 985 // this should not be set if the `collapse` key is removed from nbformat
985 986 this.dirty = true;
986 987 };
987 988
988 989
989 990 Notebook.prototype.expand_all_output = function () {
990 991 var ncells = this.ncells();
991 992 var cells = this.get_cells();
992 993 for (var i=0; i<ncells; i++) {
993 994 if (cells[i] instanceof IPython.CodeCell) {
994 995 cells[i].output_area.expand();
995 996 cells[i].output_area.unscroll_area();
996 997 }
997 998 };
998 999 // this should not be set if the `collapse` key is removed from nbformat
999 1000 this.dirty = true;
1000 1001 };
1001 1002
1002 1003
1003 1004 Notebook.prototype.clear_all_output = function () {
1004 1005 var ncells = this.ncells();
1005 1006 var cells = this.get_cells();
1006 1007 for (var i=0; i<ncells; i++) {
1007 1008 if (cells[i] instanceof IPython.CodeCell) {
1008 1009 cells[i].clear_output(true,true,true);
1009 1010 // Make all In[] prompts blank, as well
1010 1011 // TODO: make this configurable (via checkbox?)
1011 1012 cells[i].set_input_prompt();
1012 1013 }
1013 1014 };
1014 1015 this.dirty = true;
1015 1016 };
1016 1017
1017 1018
1018 1019 // Other cell functions: line numbers, ...
1019 1020
1020 1021 Notebook.prototype.cell_toggle_line_numbers = function() {
1021 1022 this.get_selected_cell().toggle_line_numbers();
1022 1023 };
1023 1024
1024 1025 // Kernel related things
1025 1026
1026 1027 Notebook.prototype.start_kernel = function () {
1027 1028 var base_url = $('body').data('baseKernelUrl') + "kernels";
1028 1029 this.kernel = new IPython.Kernel(base_url);
1029 1030 this.kernel.start(this.notebook_id);
1030 1031 // Now that the kernel has been created, tell the CodeCells about it.
1031 1032 var ncells = this.ncells();
1032 1033 for (var i=0; i<ncells; i++) {
1033 1034 var cell = this.get_cell(i);
1034 1035 if (cell instanceof IPython.CodeCell) {
1035 1036 cell.set_kernel(this.kernel)
1036 1037 };
1037 1038 };
1038 1039 };
1039 1040
1040 1041
1041 1042 Notebook.prototype.restart_kernel = function () {
1042 1043 var that = this;
1043 1044 var dialog = $('<div/>');
1044 1045 dialog.html('Do you want to restart the current kernel? You will lose all variables defined in it.');
1045 1046 $(document).append(dialog);
1046 1047 dialog.dialog({
1047 1048 resizable: false,
1048 1049 modal: true,
1049 1050 title: "Restart kernel or continue running?",
1050 1051 closeText: '',
1051 1052 buttons : {
1052 1053 "Restart": function () {
1053 1054 that.kernel.restart();
1054 1055 $(this).dialog('close');
1055 1056 },
1056 1057 "Continue running": function () {
1057 1058 $(this).dialog('close');
1058 1059 }
1059 1060 }
1060 1061 });
1061 1062 };
1062 1063
1063 1064
1064 1065 Notebook.prototype.execute_selected_cell = function (options) {
1065 1066 // add_new: should a new cell be added if we are at the end of the nb
1066 1067 // terminal: execute in terminal mode, which stays in the current cell
1067 1068 default_options = {terminal: false, add_new: true};
1068 1069 $.extend(default_options, options);
1069 1070 var that = this;
1070 1071 var cell = that.get_selected_cell();
1071 1072 var cell_index = that.find_cell_index(cell);
1072 1073 if (cell instanceof IPython.CodeCell) {
1073 1074 cell.execute();
1074 1075 } else if (cell instanceof IPython.HTMLCell) {
1075 1076 cell.render();
1076 1077 }
1077 1078 if (default_options.terminal) {
1078 1079 cell.select_all();
1079 1080 } else {
1080 1081 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
1081 1082 that.insert_cell_below('code');
1082 1083 // If we are adding a new cell at the end, scroll down to show it.
1083 1084 that.scroll_to_bottom();
1084 1085 } else {
1085 1086 that.select(cell_index+1);
1086 1087 };
1087 1088 };
1088 1089 this.dirty = true;
1089 1090 };
1090 1091
1091 1092
1092 1093 Notebook.prototype.execute_cells_below = function () {
1093 1094 this.execute_cell_range(this.get_selected_index(), this.ncells());
1094 1095 that.scroll_to_bottom();
1095 1096 };
1096 1097
1097 1098 Notebook.prototype.execute_cells_above = function () {
1098 1099 this.execute_cell_range(0, this.get_selected_index());
1099 1100 };
1100 1101
1101 1102 Notebook.prototype.execute_all_cells = function () {
1102 1103 this.execute_cell_range(0, this.ncells());
1103 1104 that.scroll_to_bottom();
1104 1105 };
1105 1106
1106 1107 Notebook.prototype.execute_cell_range = function (start, end) {
1107 1108 for (var i=start; i<end; i++) {
1108 1109 this.select(i);
1109 1110 this.execute_selected_cell({add_new:false});
1110 1111 };
1111 1112 };
1112 1113
1113 1114 // Persistance and loading
1114 1115
1115 1116 Notebook.prototype.get_notebook_id = function () {
1116 1117 return this.notebook_id;
1117 1118 };
1118 1119
1119 1120
1120 1121 Notebook.prototype.get_notebook_name = function () {
1121 1122 return this.notebook_name;
1122 1123 };
1123 1124
1124 1125
1125 1126 Notebook.prototype.set_notebook_name = function (name) {
1126 1127 this.notebook_name = name;
1127 1128 };
1128 1129
1129 1130
1130 1131 Notebook.prototype.test_notebook_name = function (nbname) {
1131 1132 nbname = nbname || '';
1132 1133 if (this.notebook_name_blacklist_re.test(nbname) == false && nbname.length>0) {
1133 1134 return true;
1134 1135 } else {
1135 1136 return false;
1136 1137 };
1137 1138 };
1138 1139
1139 1140
1140 1141 Notebook.prototype.fromJSON = function (data) {
1141 1142 var ncells = this.ncells();
1142 1143 var i;
1143 1144 for (i=0; i<ncells; i++) {
1144 1145 // Always delete cell 0 as they get renumbered as they are deleted.
1145 1146 this.delete_cell(0);
1146 1147 };
1147 1148 // Save the metadata and name.
1148 1149 this.metadata = data.metadata;
1149 1150 this.notebook_name = data.metadata.name;
1150 1151 // Only handle 1 worksheet for now.
1151 1152 var worksheet = data.worksheets[0];
1152 1153 if (worksheet !== undefined) {
1153 1154 if (worksheet.metadata) {
1154 1155 this.worksheet_metadata = worksheet.metadata;
1155 1156 }
1156 1157 var new_cells = worksheet.cells;
1157 1158 ncells = new_cells.length;
1158 1159 var cell_data = null;
1159 1160 var new_cell = null;
1160 1161 for (i=0; i<ncells; i++) {
1161 1162 cell_data = new_cells[i];
1162 1163 // VERSIONHACK: plaintext -> raw
1163 1164 // handle never-released plaintext name for raw cells
1164 1165 if (cell_data.cell_type === 'plaintext'){
1165 1166 cell_data.cell_type = 'raw';
1166 1167 }
1167 1168
1168 1169 new_cell = this.insert_cell_below(cell_data.cell_type);
1169 1170 new_cell.fromJSON(cell_data);
1170 1171 };
1171 1172 };
1172 1173 if (data.worksheets.length > 1) {
1173 1174 var dialog = $('<div/>');
1174 1175 dialog.html("This notebook has " + data.worksheets.length + " worksheets, " +
1175 1176 "but this version of IPython can only handle the first. " +
1176 1177 "If you save this notebook, worksheets after the first will be lost."
1177 1178 );
1178 1179 this.element.append(dialog);
1179 1180 dialog.dialog({
1180 1181 resizable: false,
1181 1182 modal: true,
1182 1183 title: "Multiple worksheets",
1183 1184 closeText: "",
1184 1185 close: function(event, ui) {$(this).dialog('destroy').remove();},
1185 1186 buttons : {
1186 1187 "OK": function () {
1187 1188 $(this).dialog('close');
1188 1189 }
1189 1190 },
1190 1191 width: 400
1191 1192 });
1192 1193 }
1193 1194 };
1194 1195
1195 1196
1196 1197 Notebook.prototype.toJSON = function () {
1197 1198 var cells = this.get_cells();
1198 1199 var ncells = cells.length;
1199 1200 var cell_array = new Array(ncells);
1200 1201 for (var i=0; i<ncells; i++) {
1201 1202 cell_array[i] = cells[i].toJSON();
1202 1203 };
1203 1204 var data = {
1204 1205 // Only handle 1 worksheet for now.
1205 1206 worksheets : [{
1206 1207 cells: cell_array,
1207 1208 metadata: this.worksheet_metadata
1208 1209 }],
1209 1210 metadata : this.metadata
1210 1211 };
1211 1212 return data;
1212 1213 };
1213 1214
1214 1215 Notebook.prototype.save_notebook = function () {
1215 1216 // We may want to move the name/id/nbformat logic inside toJSON?
1216 1217 var data = this.toJSON();
1217 1218 data.metadata.name = this.notebook_name;
1218 1219 data.nbformat = this.nbformat;
1219 1220 data.nbformat_minor = this.nbformat_minor;
1220 1221 // We do the call with settings so we can set cache to false.
1221 1222 var settings = {
1222 1223 processData : false,
1223 1224 cache : false,
1224 1225 type : "PUT",
1225 1226 data : JSON.stringify(data),
1226 1227 headers : {'Content-Type': 'application/json'},
1227 1228 success : $.proxy(this.save_notebook_success,this),
1228 1229 error : $.proxy(this.save_notebook_error,this)
1229 1230 };
1230 1231 $([IPython.events]).trigger('notebook_saving.Notebook');
1231 1232 var url = $('body').data('baseProjectUrl') + 'notebooks/' + this.notebook_id;
1232 1233 $.ajax(url, settings);
1233 1234 };
1234 1235
1235 1236
1236 1237 Notebook.prototype.save_notebook_success = function (data, status, xhr) {
1237 1238 this.dirty = false;
1238 1239 $([IPython.events]).trigger('notebook_saved.Notebook');
1239 1240 };
1240 1241
1241 1242
1242 1243 Notebook.prototype.save_notebook_error = function (xhr, status, error_msg) {
1243 1244 $([IPython.events]).trigger('notebook_save_failed.Notebook');
1244 1245 };
1245 1246
1246 1247
1247 1248 Notebook.prototype.load_notebook = function (notebook_id) {
1248 1249 var that = this;
1249 1250 this.notebook_id = notebook_id;
1250 1251 // We do the call with settings so we can set cache to false.
1251 1252 var settings = {
1252 1253 processData : false,
1253 1254 cache : false,
1254 1255 type : "GET",
1255 1256 dataType : "json",
1256 1257 success : $.proxy(this.load_notebook_success,this),
1257 1258 error : $.proxy(this.load_notebook_error,this),
1258 1259 };
1259 1260 $([IPython.events]).trigger('notebook_loading.Notebook');
1260 1261 var url = $('body').data('baseProjectUrl') + 'notebooks/' + this.notebook_id;
1261 1262 $.ajax(url, settings);
1262 1263 };
1263 1264
1264 1265
1265 1266 Notebook.prototype.load_notebook_success = function (data, status, xhr) {
1266 1267 this.fromJSON(data);
1267 1268 if (this.ncells() === 0) {
1268 1269 this.insert_cell_below('code');
1269 1270 };
1270 1271 this.dirty = false;
1271 1272 this.select(0);
1272 1273 this.scroll_to_top();
1273 1274 if (data.orig_nbformat !== undefined && data.nbformat !== data.orig_nbformat) {
1274 1275 msg = "This notebook has been converted from an older " +
1275 1276 "notebook format (v"+data.orig_nbformat+") to the current notebook " +
1276 1277 "format (v"+data.nbformat+"). The next time you save this notebook, the " +
1277 1278 "newer notebook format will be used and older verions of IPython " +
1278 1279 "may not be able to read it. To keep the older version, close the " +
1279 1280 "notebook without saving it.";
1280 1281 var dialog = $('<div/>');
1281 1282 dialog.html(msg);
1282 1283 this.element.append(dialog);
1283 1284 dialog.dialog({
1284 1285 resizable: false,
1285 1286 modal: true,
1286 1287 title: "Notebook converted",
1287 1288 closeText: "",
1288 1289 close: function(event, ui) {$(this).dialog('destroy').remove();},
1289 1290 buttons : {
1290 1291 "OK": function () {
1291 1292 $(this).dialog('close');
1292 1293 }
1293 1294 },
1294 1295 width: 400
1295 1296 });
1296 1297 } else if (data.orig_nbformat_minor !== undefined && data.nbformat_minor !== data.orig_nbformat_minor) {
1297 1298 var that = this;
1298 1299 var orig_vs = 'v' + data.nbformat + '.' + data.orig_nbformat_minor;
1299 1300 var this_vs = 'v' + data.nbformat + '.' + this.nbformat_minor;
1300 1301 msg = "This notebook is version " + orig_vs + ", but we only fully support up to " +
1301 1302 this_vs + ". You can still work with this notebook, but some features " +
1302 1303 "introduced in later notebook versions may not be available."
1303 1304
1304 1305 var dialog = $('<div/>');
1305 1306 dialog.html(msg);
1306 1307 this.element.append(dialog);
1307 1308 dialog.dialog({
1308 1309 resizable: false,
1309 1310 modal: true,
1310 1311 title: "Newer Notebook",
1311 1312 closeText: "",
1312 1313 close: function(event, ui) {$(this).dialog('destroy').remove();},
1313 1314 buttons : {
1314 1315 "OK": function () {
1315 1316 $(this).dialog('close');
1316 1317 }
1317 1318 },
1318 1319 width: 400
1319 1320 });
1320 1321
1321 1322 }
1322 1323 // Create the kernel after the notebook is completely loaded to prevent
1323 1324 // code execution upon loading, which is a security risk.
1324 1325 if (! this.read_only) {
1325 1326 this.start_kernel();
1326 1327 }
1327 1328 $([IPython.events]).trigger('notebook_loaded.Notebook');
1328 1329 };
1329 1330
1330 1331
1331 1332 Notebook.prototype.load_notebook_error = function (xhr, textStatus, errorThrow) {
1332 1333 if (xhr.status === 500) {
1333 1334 msg = "An error occurred while loading this notebook. Most likely " +
1334 1335 "this notebook is in a newer format than is supported by this " +
1335 1336 "version of IPython. This version can load notebook formats " +
1336 1337 "v"+this.nbformat+" or earlier.";
1337 1338 var dialog = $('<div/>');
1338 1339 dialog.html(msg);
1339 1340 this.element.append(dialog);
1340 1341 dialog.dialog({
1341 1342 resizable: false,
1342 1343 modal: true,
1343 1344 title: "Error loading notebook",
1344 1345 closeText: "",
1345 1346 close: function(event, ui) {$(this).dialog('destroy').remove();},
1346 1347 buttons : {
1347 1348 "OK": function () {
1348 1349 $(this).dialog('close');
1349 1350 }
1350 1351 },
1351 1352 width: 400
1352 1353 });
1353 1354 }
1354 1355 }
1355 1356
1356 1357 IPython.Notebook = Notebook;
1357 1358
1358 1359
1359 1360 return IPython;
1360 1361
1361 1362 }(IPython));
1362 1363
General Comments 0
You need to be logged in to leave comments. Login now