Show More
@@ -126,7 +126,7 b' class NotebookRootHandler(web.RequestHandler):' | |||||
126 |
|
126 | |||
127 | def get(self): |
|
127 | def get(self): | |
128 | files = os.listdir(os.getcwd()) |
|
128 | files = os.listdir(os.getcwd()) | |
129 | files = [file for file in files if file.endswith(".nb")] |
|
129 | files = [file for file in files if file.endswith(".ipynb")] | |
130 | self.write(json.dumps(files)) |
|
130 | self.write(json.dumps(files)) | |
131 |
|
131 | |||
132 |
|
132 | |||
@@ -135,7 +135,9 b' class NotebookHandler(web.RequestHandler):' | |||||
135 | SUPPORTED_METHODS = ("GET", "DELETE", "PUT") |
|
135 | SUPPORTED_METHODS = ("GET", "DELETE", "PUT") | |
136 |
|
136 | |||
137 | def find_path(self, filename): |
|
137 | def find_path(self, filename): | |
138 |
filename = urllib.unquote(filename) |
|
138 | filename = urllib.unquote(filename) | |
|
139 | if not filename.endswith('.ipynb'): | |||
|
140 | raise web.HTTPError(400) | |||
139 | path = os.path.join(os.getcwd(), filename) |
|
141 | path = os.path.join(os.getcwd(), filename) | |
140 | return path |
|
142 | return path | |
141 |
|
143 |
@@ -1,26 +1,6 b'' | |||||
1 | var IPYTHON = {}; |
|
1 | var IPYTHON = {}; | |
2 |
|
2 | |||
3 |
|
3 | |||
4 |
|
||||
5 | // $.get("/notebooks/number2.nb",function (data, status, xhr) {console.log(data);}); |
|
|||
6 | // |
|
|||
7 | // settings = { |
|
|||
8 | // processData : false, |
|
|||
9 | // cache : false, |
|
|||
10 | // type : "DELETE", |
|
|||
11 | // success : function (data, status, xhr) {console.log(data);} |
|
|||
12 | // } |
|
|||
13 | // $.ajax("/notebooks/number2.nb",settings) |
|
|||
14 | // |
|
|||
15 | // settings = { |
|
|||
16 | // processData : false, |
|
|||
17 | // cache : false, |
|
|||
18 | // type : "PUT", |
|
|||
19 | // success : function (data, status, xhr) {console.log(data);} |
|
|||
20 | // } |
|
|||
21 | // $.ajax("/notebooks/number2.nb",settings) |
|
|||
22 |
|
||||
23 |
|
||||
24 | //============================================================================ |
|
4 | //============================================================================ | |
25 | // Utilities |
|
5 | // Utilities | |
26 | //============================================================================ |
|
6 | //============================================================================ | |
@@ -82,6 +62,7 b' function fixConsole(txt) {' | |||||
82 | return txt.trim() |
|
62 | return txt.trim() | |
83 | } |
|
63 | } | |
84 |
|
64 | |||
|
65 | ||||
85 | //============================================================================ |
|
66 | //============================================================================ | |
86 | // Notebook |
|
67 | // Notebook | |
87 | //============================================================================ |
|
68 | //============================================================================ | |
@@ -94,6 +75,10 b' var Notebook = function (selector) {' | |||||
94 | this.next_prompt_number = 1; |
|
75 | this.next_prompt_number = 1; | |
95 | this.kernel = null; |
|
76 | this.kernel = null; | |
96 | this.msg_cell_map = {}; |
|
77 | this.msg_cell_map = {}; | |
|
78 | this.filename = null; | |||
|
79 | this.notebook_load_re = /%notebook load/ | |||
|
80 | this.notebook_save_re = /%notebook save/ | |||
|
81 | this.notebook_filename_re = /(\w)+.ipynb/ | |||
97 | this.bind_events(); |
|
82 | this.bind_events(); | |
98 | this.start_kernel(); |
|
83 | this.start_kernel(); | |
99 | }; |
|
84 | }; | |
@@ -113,12 +98,29 b' Notebook.prototype.bind_events = function () {' | |||||
113 | // The focus is not quite working here. |
|
98 | // The focus is not quite working here. | |
114 | var cell = that.selected_cell(); |
|
99 | var cell = that.selected_cell(); | |
115 | var cell_index = that.find_cell_index(cell); |
|
100 | var cell_index = that.find_cell_index(cell); | |
|
101 | // TODO: the logic here needs to be moved into appropriate | |||
|
102 | // methods of Notebook. | |||
116 | if (cell instanceof CodeCell) { |
|
103 | if (cell instanceof CodeCell) { | |
117 | event.preventDefault(); |
|
104 | event.preventDefault(); | |
118 | cell.clear_output(); |
|
105 | cell.clear_output(); | |
119 | cell.hide_output_prompt(); |
|
106 | cell.hide_output_prompt(); | |
120 |
var |
|
107 | var code = cell.get_code(); | |
121 | that.msg_cell_map[msg_id] = cell.cell_id; |
|
108 | if (that.notebook_load_re.test(code)) { | |
|
109 | var code_parts = code.split(' '); | |||
|
110 | if (code_parts.length === 3) { | |||
|
111 | that.load_notebook(code_parts[2]); | |||
|
112 | }; | |||
|
113 | } else if (that.notebook_save_re.test(code)) { | |||
|
114 | var code_parts = code.split(' '); | |||
|
115 | if (code_parts.length === 3) { | |||
|
116 | that.save_notebook(code_parts[2]); | |||
|
117 | } else { | |||
|
118 | that.save_notebook() | |||
|
119 | }; | |||
|
120 | } else { | |||
|
121 | var msg_id = that.kernel.execute(cell.get_code()); | |||
|
122 | that.msg_cell_map[msg_id] = cell.cell_id; | |||
|
123 | }; | |||
122 | if (cell_index === (that.ncells()-1)) { |
|
124 | if (cell_index === (that.ncells()-1)) { | |
123 | that.insert_code_cell_after(); |
|
125 | that.insert_code_cell_after(); | |
124 | } else { |
|
126 | } else { | |
@@ -129,7 +131,7 b' Notebook.prototype.bind_events = function () {' | |||||
129 | event.preventDefault(); |
|
131 | event.preventDefault(); | |
130 | var cell = that.selected_cell(); |
|
132 | var cell = that.selected_cell(); | |
131 | if (cell instanceof CodeCell) { |
|
133 | if (cell instanceof CodeCell) { | |
132 | var ta = cell.element.find("textarea.input_area"); |
|
134 | var ta = cell.element.find("textarea.input_textarea"); | |
133 | ta.val(ta.val() + " "); |
|
135 | ta.val(ta.val() + " "); | |
134 | }; |
|
136 | }; | |
135 | }; |
|
137 | }; | |
@@ -386,8 +388,7 b' Notebook.prototype.text_to_code = function (index) {' | |||||
386 | if (source_cell instanceof TextCell) { |
|
388 | if (source_cell instanceof TextCell) { | |
387 | this.insert_code_cell_after(i); |
|
389 | this.insert_code_cell_after(i); | |
388 | var target_cell = this.cells()[i+1]; |
|
390 | var target_cell = this.cells()[i+1]; | |
389 | var text = source_element.find("textarea.text_cell_input").val(); |
|
391 | target_cell.set_code(source_cell.get_text()); | |
390 | target_cell.element.find("textarea.input_area").val(text); |
|
|||
391 | source_element.remove(); |
|
392 | source_element.remove(); | |
392 | }; |
|
393 | }; | |
393 | }; |
|
394 | }; | |
@@ -401,12 +402,9 b' Notebook.prototype.code_to_text = function (index) {' | |||||
401 | if (source_cell instanceof CodeCell) { |
|
402 | if (source_cell instanceof CodeCell) { | |
402 | this.insert_text_cell_after(i); |
|
403 | this.insert_text_cell_after(i); | |
403 | var target_cell = this.cells()[i+1]; |
|
404 | var target_cell = this.cells()[i+1]; | |
404 |
var text = source_ |
|
405 | var text = source_cell.get_code(); | |
405 | if (text === "") {text = target_cell.placeholder;}; |
|
406 | if (text === "") {text = target_cell.placeholder;}; | |
406 |
target_cell. |
|
407 | target_cell.set_text(text); | |
407 | target_cell.element.find("textarea.text_cell_input").html(text); |
|
|||
408 | target_cell.element.find("div.text_cell_render").html(text); |
|
|||
409 |
|
||||
410 | source_element.remove(); |
|
408 | source_element.remove(); | |
411 | }; |
|
409 | }; | |
412 | }; |
|
410 | }; | |
@@ -476,6 +474,94 b' Notebook.prototype._handle_execute_reply = function (reply, cell) {' | |||||
476 | }; |
|
474 | }; | |
477 |
|
475 | |||
478 |
|
476 | |||
|
477 | // Persistance and loading | |||
|
478 | ||||
|
479 | ||||
|
480 | Notebook.prototype.fromJSON = function (data) { | |||
|
481 | var ncells = this.ncells(); | |||
|
482 | for (var i=0; i<ncells; i++) { | |||
|
483 | // Always delete cell 0 as they get renumbered as they are deleted. | |||
|
484 | this.delete_cell(0); | |||
|
485 | }; | |||
|
486 | var new_cells = data.cells; | |||
|
487 | ncells = new_cells.length; | |||
|
488 | var cell_data = null; | |||
|
489 | for (var i=0; i<ncells; i++) { | |||
|
490 | cell_data = new_cells[i]; | |||
|
491 | if (cell_data.cell_type == 'code') { | |||
|
492 | this.insert_code_cell_after(); | |||
|
493 | this.selected_cell().fromJSON(cell_data); | |||
|
494 | } else if (cell_data.cell_type === 'text') { | |||
|
495 | this.insert_text_cell_after(); | |||
|
496 | this.selected_cell().fromJSON(cell_data); | |||
|
497 | }; | |||
|
498 | }; | |||
|
499 | }; | |||
|
500 | ||||
|
501 | ||||
|
502 | Notebook.prototype.toJSON = function () { | |||
|
503 | var cells = this.cells(); | |||
|
504 | var ncells = cells.length; | |||
|
505 | cell_array = new Array(ncells); | |||
|
506 | for (var i=0; i<ncells; i++) { | |||
|
507 | cell_array[i] = cells[i].toJSON(); | |||
|
508 | }; | |||
|
509 | json = { | |||
|
510 | cells : cell_array | |||
|
511 | }; | |||
|
512 | return json | |||
|
513 | }; | |||
|
514 | ||||
|
515 | ||||
|
516 | Notebook.prototype.test_filename = function (filename) { | |||
|
517 | if (this.notebook_filename_re.test(filename)) { | |||
|
518 | return true; | |||
|
519 | } else { | |||
|
520 | var bad_filename = $('<div/>'); | |||
|
521 | bad_filename.html( | |||
|
522 | "The filename you entered (" + filename + ") is not valid. Notebook filenames must have the following form: foo.ipynb" | |||
|
523 | ); | |||
|
524 | bad_filename.dialog({title: 'Invalid filename', modal: true}); | |||
|
525 | return false; | |||
|
526 | }; | |||
|
527 | }; | |||
|
528 | ||||
|
529 | Notebook.prototype.save_notebook = function (filename) { | |||
|
530 | this.filename = filename || this.filename || ''; | |||
|
531 | if (this.filename === '') { | |||
|
532 | var no_filename = $('<div/>'); | |||
|
533 | no_filename.html( | |||
|
534 | "This notebook has no filename, please specify a filename of the form: foo.ipynb" | |||
|
535 | ); | |||
|
536 | no_filename.dialog({title: 'Missing filename', modal: true}); | |||
|
537 | return; | |||
|
538 | } | |||
|
539 | if (!this.test_filename(this.filename)) {return;} | |||
|
540 | var thedata = this.toJSON(); | |||
|
541 | var settings = { | |||
|
542 | processData : false, | |||
|
543 | cache : false, | |||
|
544 | type : "PUT", | |||
|
545 | data : JSON.stringify(thedata), | |||
|
546 | success : function (data, status, xhr) {console.log(data);} | |||
|
547 | }; | |||
|
548 | $.ajax("/notebooks/" + this.filename, settings); | |||
|
549 | }; | |||
|
550 | ||||
|
551 | ||||
|
552 | Notebook.prototype.load_notebook = function (filename) { | |||
|
553 | if (!this.test_filename(filename)) {return;} | |||
|
554 | var that = this; | |||
|
555 | $.getJSON("/notebooks/" + filename, | |||
|
556 | function (data, status, xhr) { | |||
|
557 | that.fromJSON(data); | |||
|
558 | that.filename = filename; | |||
|
559 | that.kernel.restart(); | |||
|
560 | } | |||
|
561 | ); | |||
|
562 | } | |||
|
563 | ||||
|
564 | ||||
479 | //============================================================================ |
|
565 | //============================================================================ | |
480 | // Cell |
|
566 | // Cell | |
481 | //============================================================================ |
|
567 | //============================================================================ | |
@@ -620,16 +706,32 b' CodeCell.prototype.set_output_prompt = function (number) {' | |||||
620 | this.element.find('div.output_prompt').html('Out[' + n + ']:'); |
|
706 | this.element.find('div.output_prompt').html('Out[' + n + ']:'); | |
621 | }; |
|
707 | }; | |
622 |
|
708 | |||
|
709 | ||||
623 | CodeCell.prototype.hide_output_prompt = function () { |
|
710 | CodeCell.prototype.hide_output_prompt = function () { | |
624 | this.element.find('div.output_prompt').hide(); |
|
711 | this.element.find('div.output_prompt').hide(); | |
625 | }; |
|
712 | }; | |
626 |
|
713 | |||
|
714 | ||||
627 | CodeCell.prototype.show_output_prompt = function () { |
|
715 | CodeCell.prototype.show_output_prompt = function () { | |
628 | this.element.find('div.output_prompt').show(); |
|
716 | this.element.find('div.output_prompt').show(); | |
629 | }; |
|
717 | }; | |
630 |
|
718 | |||
|
719 | ||||
631 | CodeCell.prototype.get_code = function () { |
|
720 | CodeCell.prototype.get_code = function () { | |
632 | return this.element.find("textarea.input_area").val(); |
|
721 | return this.element.find("textarea.input_textarea").val(); | |
|
722 | }; | |||
|
723 | ||||
|
724 | ||||
|
725 | CodeCell.prototype.set_code = function (code) { | |||
|
726 | return this.element.find("textarea.input_textarea").val(code); | |||
|
727 | }; | |||
|
728 | ||||
|
729 | ||||
|
730 | CodeCell.prototype.fromJSON = function (data) { | |||
|
731 | if (data.cell_type === 'code') { | |||
|
732 | this.set_code(data.code); | |||
|
733 | this.set_input_prompt(data.prompt_number); | |||
|
734 | }; | |||
633 | }; |
|
735 | }; | |
634 |
|
736 | |||
635 |
|
737 | |||
@@ -640,6 +742,7 b' CodeCell.prototype.toJSON = function () {' | |||||
640 | prompt_number : this.input_prompt_number |
|
742 | prompt_number : this.input_prompt_number | |
641 | }; |
|
743 | }; | |
642 | }; |
|
744 | }; | |
|
745 | ||||
643 | //============================================================================ |
|
746 | //============================================================================ | |
644 | // TextCell |
|
747 | // TextCell | |
645 | //============================================================================ |
|
748 | //============================================================================ | |
@@ -714,6 +817,32 b' TextCell.prototype.config_mathjax = function () {' | |||||
714 | }; |
|
817 | }; | |
715 |
|
818 | |||
716 |
|
819 | |||
|
820 | TextCell.prototype.get_text = function() { | |||
|
821 | return this.element.find("textarea.text_cell_input").val(); | |||
|
822 | }; | |||
|
823 | ||||
|
824 | ||||
|
825 | TextCell.prototype.set_text = function(text) { | |||
|
826 | this.element.find("textarea.text_cell_input").val(text); | |||
|
827 | this.element.find("textarea.text_cell_input").html(text); | |||
|
828 | this.element.find("div.text_cell_render").html(text); | |||
|
829 | }; | |||
|
830 | ||||
|
831 | ||||
|
832 | TextCell.prototype.fromJSON = function (data) { | |||
|
833 | if (data.cell_type === 'text') { | |||
|
834 | this.set_text(data.text); | |||
|
835 | }; | |||
|
836 | } | |||
|
837 | ||||
|
838 | ||||
|
839 | TextCell.prototype.toJSON = function () { | |||
|
840 | return { | |||
|
841 | cell_type : 'text', | |||
|
842 | text : this.get_text(), | |||
|
843 | }; | |||
|
844 | }; | |||
|
845 | ||||
717 | //============================================================================ |
|
846 | //============================================================================ | |
718 | // On document ready |
|
847 | // On document ready | |
719 | //============================================================================ |
|
848 | //============================================================================ |
General Comments 0
You need to be logged in to leave comments.
Login now