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