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