##// END OF EJS Templates
Added complete method of JS kernel object.
Brian Granger -
Show More
@@ -1,93 +1,105 b''
1
1
2 //============================================================================
2 //============================================================================
3 // Kernel
3 // Kernel
4 //============================================================================
4 //============================================================================
5
5
6 var IPython = (function (IPython) {
6 var IPython = (function (IPython) {
7
7
8 var utils = IPython.utils;
8 var utils = IPython.utils;
9
9
10 var Kernel = function () {
10 var Kernel = function () {
11 this.kernel_id = null;
11 this.kernel_id = null;
12 this.base_url = "/kernels";
12 this.base_url = "/kernels";
13 this.kernel_url = null;
13 this.kernel_url = null;
14 };
14 };
15
15
16
16
17 Kernel.prototype.get_msg = function (msg_type, content) {
17 Kernel.prototype.get_msg = function (msg_type, content) {
18 var msg = {
18 var msg = {
19 header : {
19 header : {
20 msg_id : utils.uuid(),
20 msg_id : utils.uuid(),
21 username : "bgranger",
21 username : "bgranger",
22 session: this.session_id,
22 session: this.session_id,
23 msg_type : msg_type
23 msg_type : msg_type
24 },
24 },
25 content : content,
25 content : content,
26 parent_header : {}
26 parent_header : {}
27 };
27 };
28 return msg;
28 return msg;
29 }
29 }
30
30
31 Kernel.prototype.start_kernel = function (callback) {
31 Kernel.prototype.start_kernel = function (callback) {
32 var that = this;
32 var that = this;
33 $.post(this.base_url,
33 $.post(this.base_url,
34 function (kernel_id) {
34 function (kernel_id) {
35 that._handle_start_kernel(kernel_id, callback);
35 that._handle_start_kernel(kernel_id, callback);
36 },
36 },
37 'json'
37 'json'
38 );
38 );
39 };
39 };
40
40
41
41
42 Kernel.prototype._handle_start_kernel = function (kernel_id, callback) {
42 Kernel.prototype._handle_start_kernel = function (kernel_id, callback) {
43 this.kernel_id = kernel_id;
43 this.kernel_id = kernel_id;
44 this.kernel_url = this.base_url + "/" + this.kernel_id;
44 this.kernel_url = this.base_url + "/" + this.kernel_id;
45 this._start_channels();
45 this._start_channels();
46 callback();
46 callback();
47 };
47 };
48
48
49
49
50 Kernel.prototype._start_channels = function () {
50 Kernel.prototype._start_channels = function () {
51 var ws_url = "ws://127.0.0.1:8888" + this.kernel_url;
51 var ws_url = "ws://127.0.0.1:8888" + this.kernel_url;
52 this.shell_channel = new WebSocket(ws_url + "/shell");
52 this.shell_channel = new WebSocket(ws_url + "/shell");
53 this.iopub_channel = new WebSocket(ws_url + "/iopub");
53 this.iopub_channel = new WebSocket(ws_url + "/iopub");
54 }
54 }
55
55
56
56
57 Kernel.prototype.execute = function (code) {
57 Kernel.prototype.execute = function (code) {
58 var content = {
58 var content = {
59 code : code,
59 code : code,
60 silent : false,
60 silent : false,
61 user_variables : [],
61 user_variables : [],
62 user_expressions : {}
62 user_expressions : {}
63 };
63 };
64 var msg = this.get_msg("execute_request", content);
64 var msg = this.get_msg("execute_request", content);
65 this.shell_channel.send(JSON.stringify(msg));
65 this.shell_channel.send(JSON.stringify(msg));
66 return msg.header.msg_id;
66 return msg.header.msg_id;
67 }
67 }
68
68
69
69
70 Kernel.prototype.complete = function (line, cursor_pos) {
71 var content = {
72 text : '',
73 line : line,
74 cursor_pos : cursor_pos
75 };
76 var msg = this.get_msg("complete_request", content);
77 this.shell_channel.send(JSON.stringify(msg));
78 return msg.header.msg_id;
79 }
80
81
70 Kernel.prototype.interrupt = function () {
82 Kernel.prototype.interrupt = function () {
71 $.post(this.kernel_url + "/interrupt");
83 $.post(this.kernel_url + "/interrupt");
72 };
84 };
73
85
74
86
75 Kernel.prototype.restart = function () {
87 Kernel.prototype.restart = function () {
76 IPython.kernel_status_widget.status_restarting();
88 IPython.kernel_status_widget.status_restarting();
77 url = this.kernel_url + "/restart"
89 url = this.kernel_url + "/restart"
78 var that = this;
90 var that = this;
79 $.post(url, function (kernel_id) {
91 $.post(url, function (kernel_id) {
80 console.log("Kernel restarted: " + kernel_id);
92 console.log("Kernel restarted: " + kernel_id);
81 that.kernel_id = kernel_id;
93 that.kernel_id = kernel_id;
82 that.kernel_url = that.base_url + "/" + that.kernel_id;
94 that.kernel_url = that.base_url + "/" + that.kernel_id;
83 IPython.kernel_status_widget.status_idle();
95 IPython.kernel_status_widget.status_idle();
84 }, 'json');
96 }, 'json');
85 };
97 };
86
98
87
99
88 IPython.Kernel = Kernel;
100 IPython.Kernel = Kernel;
89
101
90 return IPython;
102 return IPython;
91
103
92 }(IPython));
104 }(IPython));
93
105
@@ -1,604 +1,606 b''
1
1
2 //============================================================================
2 //============================================================================
3 // Notebook
3 // Notebook
4 //============================================================================
4 //============================================================================
5
5
6 var IPython = (function (IPython) {
6 var IPython = (function (IPython) {
7
7
8 var utils = IPython.utils;
8 var utils = IPython.utils;
9
9
10 var Notebook = function (selector) {
10 var Notebook = function (selector) {
11 this.element = $(selector);
11 this.element = $(selector);
12 this.element.scroll();
12 this.element.scroll();
13 this.element.data("notebook", this);
13 this.element.data("notebook", this);
14 this.next_prompt_number = 1;
14 this.next_prompt_number = 1;
15 this.kernel = null;
15 this.kernel = null;
16 this.msg_cell_map = {};
16 this.msg_cell_map = {};
17 this.filename = null;
17 this.filename = null;
18 this.notebook_load_re = /%notebook load/
18 this.notebook_load_re = /%notebook load/
19 this.notebook_save_re = /%notebook save/
19 this.notebook_save_re = /%notebook save/
20 this.notebook_filename_re = /(\w)+.ipynb/
20 this.notebook_filename_re = /(\w)+.ipynb/
21 this.style();
21 this.style();
22 this.create_elements();
22 this.create_elements();
23 this.bind_events();
23 this.bind_events();
24 this.start_kernel();
24 this.start_kernel();
25 };
25 };
26
26
27
27
28 Notebook.prototype.style = function () {
28 Notebook.prototype.style = function () {
29 $('div#notebook').addClass('border-box-sizing');
29 $('div#notebook').addClass('border-box-sizing');
30 };
30 };
31
31
32
32
33 Notebook.prototype.create_elements = function () {
33 Notebook.prototype.create_elements = function () {
34 // We add this end_space div to the end of the notebook div to:
34 // We add this end_space div to the end of the notebook div to:
35 // i) provide a margin between the last cell and the end of the notebook
35 // i) provide a margin between the last cell and the end of the notebook
36 // ii) to prevent the div from scrolling up when the last cell is being
36 // ii) to prevent the div from scrolling up when the last cell is being
37 // edited, but is too low on the page, which browsers will do automatically.
37 // edited, but is too low on the page, which browsers will do automatically.
38 this.element.append($('<div class="end_space"></div>').height(50));
38 this.element.append($('<div class="end_space"></div>').height(50));
39 $('div#notebook').addClass('border-box-sizing');
39 $('div#notebook').addClass('border-box-sizing');
40 };
40 };
41
41
42
42
43 Notebook.prototype.bind_events = function () {
43 Notebook.prototype.bind_events = function () {
44 var that = this;
44 var that = this;
45 $(document).keydown(function (event) {
45 $(document).keydown(function (event) {
46 // console.log(event);
46 // console.log(event);
47 if (event.which === 38) {
47 if (event.which === 38) {
48 var cell = that.selected_cell();
48 var cell = that.selected_cell();
49 if (cell.at_top()) {
49 if (cell.at_top()) {
50 event.preventDefault();
50 event.preventDefault();
51 that.select_prev();
51 that.select_prev();
52 };
52 };
53 } else if (event.which === 40) {
53 } else if (event.which === 40) {
54 var cell = that.selected_cell();
54 var cell = that.selected_cell();
55 if (cell.at_bottom()) {
55 if (cell.at_bottom()) {
56 event.preventDefault();
56 event.preventDefault();
57 that.select_next();
57 that.select_next();
58 };
58 };
59 } else if (event.which === 13 && event.shiftKey) {
59 } else if (event.which === 13 && event.shiftKey) {
60 that.execute_selected_cell(true);
60 that.execute_selected_cell(true);
61 return false;
61 return false;
62 };
62 };
63 });
63 });
64
64
65 this.element.bind('collapse_pager', function () {
65 this.element.bind('collapse_pager', function () {
66 var app_height = $('div#notebook_app').height(); // content height
66 var app_height = $('div#notebook_app').height(); // content height
67 var splitter_height = $('div#pager_splitter').outerHeight(true);
67 var splitter_height = $('div#pager_splitter').outerHeight(true);
68 var new_height = app_height - splitter_height;
68 var new_height = app_height - splitter_height;
69 that.element.animate({height : new_height + 'px'}, 'fast');
69 that.element.animate({height : new_height + 'px'}, 'fast');
70 });
70 });
71
71
72 this.element.bind('expand_pager', function () {
72 this.element.bind('expand_pager', function () {
73 var app_height = $('div#notebook_app').height(); // content height
73 var app_height = $('div#notebook_app').height(); // content height
74 var splitter_height = $('div#pager_splitter').outerHeight(true);
74 var splitter_height = $('div#pager_splitter').outerHeight(true);
75 var pager_height = $('div#pager').outerHeight(true);
75 var pager_height = $('div#pager').outerHeight(true);
76 var new_height = app_height - pager_height - splitter_height;
76 var new_height = app_height - pager_height - splitter_height;
77 that.element.animate({height : new_height + 'px'}, 'fast');
77 that.element.animate({height : new_height + 'px'}, 'fast');
78 });
78 });
79
79
80 this.element.bind('collapse_left_panel', function () {
80 this.element.bind('collapse_left_panel', function () {
81 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
81 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
82 var new_margin = splitter_width;
82 var new_margin = splitter_width;
83 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
83 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
84 });
84 });
85
85
86 this.element.bind('expand_left_panel', function () {
86 this.element.bind('expand_left_panel', function () {
87 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
87 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
88 var left_panel_width = IPython.left_panel.width;
88 var left_panel_width = IPython.left_panel.width;
89 var new_margin = splitter_width + left_panel_width;
89 var new_margin = splitter_width + left_panel_width;
90 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
90 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
91 });
91 });
92 };
92 };
93
93
94
94
95 Notebook.prototype.scroll_to_bottom = function () {
95 Notebook.prototype.scroll_to_bottom = function () {
96 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
96 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
97 };
97 };
98
98
99 // Cell indexing, retrieval, etc.
99 // Cell indexing, retrieval, etc.
100
100
101
101
102 Notebook.prototype.cell_elements = function () {
102 Notebook.prototype.cell_elements = function () {
103 return this.element.children("div.cell");
103 return this.element.children("div.cell");
104 }
104 }
105
105
106
106
107 Notebook.prototype.ncells = function (cell) {
107 Notebook.prototype.ncells = function (cell) {
108 return this.cell_elements().length;
108 return this.cell_elements().length;
109 }
109 }
110
110
111
111
112 // TODO: we are often calling cells as cells()[i], which we should optimize
112 // TODO: we are often calling cells as cells()[i], which we should optimize
113 // to cells(i) or a new method.
113 // to cells(i) or a new method.
114 Notebook.prototype.cells = function () {
114 Notebook.prototype.cells = function () {
115 return this.cell_elements().toArray().map(function (e) {
115 return this.cell_elements().toArray().map(function (e) {
116 return $(e).data("cell");
116 return $(e).data("cell");
117 });
117 });
118 }
118 }
119
119
120
120
121 Notebook.prototype.find_cell_index = function (cell) {
121 Notebook.prototype.find_cell_index = function (cell) {
122 var result = null;
122 var result = null;
123 this.cell_elements().filter(function (index) {
123 this.cell_elements().filter(function (index) {
124 if ($(this).data("cell") === cell) {
124 if ($(this).data("cell") === cell) {
125 result = index;
125 result = index;
126 };
126 };
127 });
127 });
128 return result;
128 return result;
129 };
129 };
130
130
131
131
132 Notebook.prototype.index_or_selected = function (index) {
132 Notebook.prototype.index_or_selected = function (index) {
133 return index || this.selected_index() || 0;
133 return index || this.selected_index() || 0;
134 }
134 }
135
135
136
136
137 Notebook.prototype.select = function (index) {
137 Notebook.prototype.select = function (index) {
138 if (index !== undefined && index >= 0 && index < this.ncells()) {
138 if (index !== undefined && index >= 0 && index < this.ncells()) {
139 if (this.selected_index() !== null) {
139 if (this.selected_index() !== null) {
140 this.selected_cell().unselect();
140 this.selected_cell().unselect();
141 };
141 };
142 this.cells()[index].select();
142 this.cells()[index].select();
143 if (index === (this.ncells()-1)) {
143 if (index === (this.ncells()-1)) {
144 this.scroll_to_bottom();
144 this.scroll_to_bottom();
145 };
145 };
146 };
146 };
147 return this;
147 return this;
148 };
148 };
149
149
150
150
151 Notebook.prototype.select_next = function () {
151 Notebook.prototype.select_next = function () {
152 var index = this.selected_index();
152 var index = this.selected_index();
153 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
153 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
154 this.select(index+1);
154 this.select(index+1);
155 };
155 };
156 return this;
156 return this;
157 };
157 };
158
158
159
159
160 Notebook.prototype.select_prev = function () {
160 Notebook.prototype.select_prev = function () {
161 var index = this.selected_index();
161 var index = this.selected_index();
162 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
162 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
163 this.select(index-1);
163 this.select(index-1);
164 };
164 };
165 return this;
165 return this;
166 };
166 };
167
167
168
168
169 Notebook.prototype.selected_index = function () {
169 Notebook.prototype.selected_index = function () {
170 var result = null;
170 var result = null;
171 this.cell_elements().filter(function (index) {
171 this.cell_elements().filter(function (index) {
172 if ($(this).data("cell").selected === true) {
172 if ($(this).data("cell").selected === true) {
173 result = index;
173 result = index;
174 };
174 };
175 });
175 });
176 return result;
176 return result;
177 };
177 };
178
178
179
179
180 Notebook.prototype.cell_for_msg = function (msg_id) {
180 Notebook.prototype.cell_for_msg = function (msg_id) {
181 var cell_id = this.msg_cell_map[msg_id];
181 var cell_id = this.msg_cell_map[msg_id];
182 var result = null;
182 var result = null;
183 this.cell_elements().filter(function (index) {
183 this.cell_elements().filter(function (index) {
184 cell = $(this).data("cell");
184 cell = $(this).data("cell");
185 if (cell.cell_id === cell_id) {
185 if (cell.cell_id === cell_id) {
186 result = cell;
186 result = cell;
187 };
187 };
188 });
188 });
189 return result;
189 return result;
190 };
190 };
191
191
192
192
193 Notebook.prototype.selected_cell = function () {
193 Notebook.prototype.selected_cell = function () {
194 return this.cell_elements().eq(this.selected_index()).data("cell");
194 return this.cell_elements().eq(this.selected_index()).data("cell");
195 }
195 }
196
196
197
197
198 // Cell insertion, deletion and moving.
198 // Cell insertion, deletion and moving.
199
199
200
200
201 Notebook.prototype.delete_cell = function (index) {
201 Notebook.prototype.delete_cell = function (index) {
202 var i = index || this.selected_index();
202 var i = index || this.selected_index();
203 if (i !== null && i >= 0 && i < this.ncells()) {
203 if (i !== null && i >= 0 && i < this.ncells()) {
204 this.cell_elements().eq(i).remove();
204 this.cell_elements().eq(i).remove();
205 if (i === (this.ncells())) {
205 if (i === (this.ncells())) {
206 this.select(i-1);
206 this.select(i-1);
207 } else {
207 } else {
208 this.select(i);
208 this.select(i);
209 };
209 };
210 };
210 };
211 return this;
211 return this;
212 };
212 };
213
213
214
214
215 Notebook.prototype.append_cell = function (cell) {
215 Notebook.prototype.append_cell = function (cell) {
216 this.element.find('div.end_space').before(cell.element);
216 this.element.find('div.end_space').before(cell.element);
217 return this;
217 return this;
218 };
218 };
219
219
220
220
221 Notebook.prototype.insert_cell_after = function (cell, index) {
221 Notebook.prototype.insert_cell_after = function (cell, index) {
222 var ncells = this.ncells();
222 var ncells = this.ncells();
223 if (ncells === 0) {
223 if (ncells === 0) {
224 this.append_cell(cell);
224 this.append_cell(cell);
225 return this;
225 return this;
226 };
226 };
227 if (index >= 0 && index < ncells) {
227 if (index >= 0 && index < ncells) {
228 this.cell_elements().eq(index).after(cell.element);
228 this.cell_elements().eq(index).after(cell.element);
229 };
229 };
230 return this
230 return this
231 };
231 };
232
232
233
233
234 Notebook.prototype.insert_cell_before = function (cell, index) {
234 Notebook.prototype.insert_cell_before = function (cell, index) {
235 var ncells = this.ncells();
235 var ncells = this.ncells();
236 if (ncells === 0) {
236 if (ncells === 0) {
237 this.append_cell(cell);
237 this.append_cell(cell);
238 return this;
238 return this;
239 };
239 };
240 if (index >= 0 && index < ncells) {
240 if (index >= 0 && index < ncells) {
241 this.cell_elements().eq(index).before(cell.element);
241 this.cell_elements().eq(index).before(cell.element);
242 };
242 };
243 return this;
243 return this;
244 };
244 };
245
245
246
246
247 Notebook.prototype.move_cell_up = function (index) {
247 Notebook.prototype.move_cell_up = function (index) {
248 var i = index || this.selected_index();
248 var i = index || this.selected_index();
249 if (i !== null && i < this.ncells() && i > 0) {
249 if (i !== null && i < this.ncells() && i > 0) {
250 var pivot = this.cell_elements().eq(i-1);
250 var pivot = this.cell_elements().eq(i-1);
251 var tomove = this.cell_elements().eq(i);
251 var tomove = this.cell_elements().eq(i);
252 if (pivot !== null && tomove !== null) {
252 if (pivot !== null && tomove !== null) {
253 tomove.detach();
253 tomove.detach();
254 pivot.before(tomove);
254 pivot.before(tomove);
255 this.select(i-1);
255 this.select(i-1);
256 };
256 };
257 };
257 };
258 return this;
258 return this;
259 }
259 }
260
260
261
261
262 Notebook.prototype.move_cell_down = function (index) {
262 Notebook.prototype.move_cell_down = function (index) {
263 var i = index || this.selected_index();
263 var i = index || this.selected_index();
264 if (i !== null && i < (this.ncells()-1) && i >= 0) {
264 if (i !== null && i < (this.ncells()-1) && i >= 0) {
265 var pivot = this.cell_elements().eq(i+1)
265 var pivot = this.cell_elements().eq(i+1)
266 var tomove = this.cell_elements().eq(i)
266 var tomove = this.cell_elements().eq(i)
267 if (pivot !== null && tomove !== null) {
267 if (pivot !== null && tomove !== null) {
268 tomove.detach();
268 tomove.detach();
269 pivot.after(tomove);
269 pivot.after(tomove);
270 this.select(i+1);
270 this.select(i+1);
271 };
271 };
272 };
272 };
273 return this;
273 return this;
274 }
274 }
275
275
276
276
277 Notebook.prototype.sort_cells = function () {
277 Notebook.prototype.sort_cells = function () {
278 var ncells = this.ncells();
278 var ncells = this.ncells();
279 var sindex = this.selected_index();
279 var sindex = this.selected_index();
280 var swapped;
280 var swapped;
281 do {
281 do {
282 swapped = false
282 swapped = false
283 for (var i=1; i<ncells; i++) {
283 for (var i=1; i<ncells; i++) {
284 current = this.cell_elements().eq(i).data("cell");
284 current = this.cell_elements().eq(i).data("cell");
285 previous = this.cell_elements().eq(i-1).data("cell");
285 previous = this.cell_elements().eq(i-1).data("cell");
286 if (previous.input_prompt_number > current.input_prompt_number) {
286 if (previous.input_prompt_number > current.input_prompt_number) {
287 this.move_cell_up(i);
287 this.move_cell_up(i);
288 swapped = true;
288 swapped = true;
289 };
289 };
290 };
290 };
291 } while (swapped);
291 } while (swapped);
292 this.select(sindex);
292 this.select(sindex);
293 return this;
293 return this;
294 };
294 };
295
295
296
296
297 Notebook.prototype.insert_code_cell_before = function (index) {
297 Notebook.prototype.insert_code_cell_before = function (index) {
298 // TODO: Bounds check for i
298 // TODO: Bounds check for i
299 var i = this.index_or_selected(index);
299 var i = this.index_or_selected(index);
300 var cell = new IPython.CodeCell(this);
300 var cell = new IPython.CodeCell(this);
301 cell.set_input_prompt(this.next_prompt_number);
301 cell.set_input_prompt(this.next_prompt_number);
302 this.next_prompt_number = this.next_prompt_number + 1;
302 this.next_prompt_number = this.next_prompt_number + 1;
303 this.insert_cell_before(cell, i);
303 this.insert_cell_before(cell, i);
304 this.select(this.find_cell_index(cell));
304 this.select(this.find_cell_index(cell));
305 return this;
305 return this;
306 }
306 }
307
307
308
308
309 Notebook.prototype.insert_code_cell_after = function (index) {
309 Notebook.prototype.insert_code_cell_after = function (index) {
310 // TODO: Bounds check for i
310 // TODO: Bounds check for i
311 var i = this.index_or_selected(index);
311 var i = this.index_or_selected(index);
312 var cell = new IPython.CodeCell(this);
312 var cell = new IPython.CodeCell(this);
313 cell.set_input_prompt(this.next_prompt_number);
313 cell.set_input_prompt(this.next_prompt_number);
314 this.next_prompt_number = this.next_prompt_number + 1;
314 this.next_prompt_number = this.next_prompt_number + 1;
315 this.insert_cell_after(cell, i);
315 this.insert_cell_after(cell, i);
316 this.select(this.find_cell_index(cell));
316 this.select(this.find_cell_index(cell));
317 return this;
317 return this;
318 }
318 }
319
319
320
320
321 Notebook.prototype.insert_text_cell_before = function (index) {
321 Notebook.prototype.insert_text_cell_before = function (index) {
322 // TODO: Bounds check for i
322 // TODO: Bounds check for i
323 var i = this.index_or_selected(index);
323 var i = this.index_or_selected(index);
324 var cell = new IPython.TextCell(this);
324 var cell = new IPython.TextCell(this);
325 cell.config_mathjax();
325 cell.config_mathjax();
326 this.insert_cell_before(cell, i);
326 this.insert_cell_before(cell, i);
327 this.select(this.find_cell_index(cell));
327 this.select(this.find_cell_index(cell));
328 return this;
328 return this;
329 }
329 }
330
330
331
331
332 Notebook.prototype.insert_text_cell_after = function (index) {
332 Notebook.prototype.insert_text_cell_after = function (index) {
333 // TODO: Bounds check for i
333 // TODO: Bounds check for i
334 var i = this.index_or_selected(index);
334 var i = this.index_or_selected(index);
335 var cell = new IPython.TextCell(this);
335 var cell = new IPython.TextCell(this);
336 cell.config_mathjax();
336 cell.config_mathjax();
337 this.insert_cell_after(cell, i);
337 this.insert_cell_after(cell, i);
338 this.select(this.find_cell_index(cell));
338 this.select(this.find_cell_index(cell));
339 return this;
339 return this;
340 }
340 }
341
341
342
342
343 Notebook.prototype.text_to_code = function (index) {
343 Notebook.prototype.text_to_code = function (index) {
344 // TODO: Bounds check for i
344 // TODO: Bounds check for i
345 var i = this.index_or_selected(index);
345 var i = this.index_or_selected(index);
346 var source_element = this.cell_elements().eq(i);
346 var source_element = this.cell_elements().eq(i);
347 var source_cell = source_element.data("cell");
347 var source_cell = source_element.data("cell");
348 if (source_cell instanceof IPython.TextCell) {
348 if (source_cell instanceof IPython.TextCell) {
349 this.insert_code_cell_after(i);
349 this.insert_code_cell_after(i);
350 var target_cell = this.cells()[i+1];
350 var target_cell = this.cells()[i+1];
351 target_cell.set_code(source_cell.get_text());
351 target_cell.set_code(source_cell.get_text());
352 source_element.remove();
352 source_element.remove();
353 };
353 };
354 };
354 };
355
355
356
356
357 Notebook.prototype.code_to_text = function (index) {
357 Notebook.prototype.code_to_text = function (index) {
358 // TODO: Bounds check for i
358 // TODO: Bounds check for i
359 var i = this.index_or_selected(index);
359 var i = this.index_or_selected(index);
360 var source_element = this.cell_elements().eq(i);
360 var source_element = this.cell_elements().eq(i);
361 var source_cell = source_element.data("cell");
361 var source_cell = source_element.data("cell");
362 if (source_cell instanceof IPython.CodeCell) {
362 if (source_cell instanceof IPython.CodeCell) {
363 this.insert_text_cell_after(i);
363 this.insert_text_cell_after(i);
364 var target_cell = this.cells()[i+1];
364 var target_cell = this.cells()[i+1];
365 var text = source_cell.get_code();
365 var text = source_cell.get_code();
366 if (text === "") {text = target_cell.placeholder;};
366 if (text === "") {text = target_cell.placeholder;};
367 target_cell.set_text(text);
367 target_cell.set_text(text);
368 source_element.remove();
368 source_element.remove();
369 target_cell.edit();
369 target_cell.edit();
370 };
370 };
371 };
371 };
372
372
373
373
374 // Cell collapsing
374 // Cell collapsing
375
375
376 Notebook.prototype.collapse = function (index) {
376 Notebook.prototype.collapse = function (index) {
377 var i = this.index_or_selected(index);
377 var i = this.index_or_selected(index);
378 this.cells()[i].collapse();
378 this.cells()[i].collapse();
379 };
379 };
380
380
381
381
382 Notebook.prototype.expand = function (index) {
382 Notebook.prototype.expand = function (index) {
383 var i = this.index_or_selected(index);
383 var i = this.index_or_selected(index);
384 this.cells()[i].expand();
384 this.cells()[i].expand();
385 };
385 };
386
386
387
387
388 // Kernel related things
388 // Kernel related things
389
389
390 Notebook.prototype.start_kernel = function () {
390 Notebook.prototype.start_kernel = function () {
391 this.kernel = new IPython.Kernel();
391 this.kernel = new IPython.Kernel();
392 this.kernel.start_kernel($.proxy(this.kernel_started, this));
392 this.kernel.start_kernel($.proxy(this.kernel_started, this));
393 };
393 };
394
394
395
395
396 Notebook.prototype.handle_shell_reply = function (e) {
396 Notebook.prototype.handle_shell_reply = function (e) {
397 reply = $.parseJSON(e.data);
397 reply = $.parseJSON(e.data);
398 var header = reply.header;
398 var header = reply.header;
399 var content = reply.content;
399 var content = reply.content;
400 var msg_type = header.msg_type;
400 var msg_type = header.msg_type;
401 // console.log(reply);
401 // console.log(reply);
402 var cell = this.cell_for_msg(reply.parent_header.msg_id);
402 var cell = this.cell_for_msg(reply.parent_header.msg_id);
403 if (msg_type === "execute_reply") {
403 if (msg_type === "execute_reply") {
404 cell.set_input_prompt(content.execution_count);
404 cell.set_input_prompt(content.execution_count);
405 } else if (msg_type === "complete_reply") {
406 console.log(content);
405 };
407 };
406 var payload = content.payload || [];
408 var payload = content.payload || [];
407 this.handle_payload(content.payload);
409 this.handle_payload(payload);
408 };
410 };
409
411
410
412
411 Notebook.prototype.handle_payload = function (payload) {
413 Notebook.prototype.handle_payload = function (payload) {
412 var l = payload.length;
414 var l = payload.length;
413 if (l > 0) {
415 if (l > 0) {
414 IPython.pager.clear();
416 IPython.pager.clear();
415 IPython.pager.expand();
417 IPython.pager.expand();
416 };
418 };
417 for (var i=0; i<l; i++) {
419 for (var i=0; i<l; i++) {
418 IPython.pager.append_text(payload[i].text);
420 IPython.pager.append_text(payload[i].text);
419 };
421 };
420 };
422 };
421
423
422
424
423 Notebook.prototype.handle_iopub_reply = function (e) {
425 Notebook.prototype.handle_iopub_reply = function (e) {
424 reply = $.parseJSON(e.data);
426 reply = $.parseJSON(e.data);
425 var content = reply.content;
427 var content = reply.content;
426 // console.log(reply);
428 // console.log(reply);
427 var msg_type = reply.header.msg_type;
429 var msg_type = reply.header.msg_type;
428 var cell = this.cell_for_msg(reply.parent_header.msg_id);
430 var cell = this.cell_for_msg(reply.parent_header.msg_id);
429 if (msg_type === "stream") {
431 if (msg_type === "stream") {
430 cell.expand();
432 cell.expand();
431 cell.append_stream(content.data + "\n");
433 cell.append_stream(content.data + "\n");
432 } else if (msg_type === "display_data") {
434 } else if (msg_type === "display_data") {
433 cell.expand();
435 cell.expand();
434 cell.append_display_data(content.data);
436 cell.append_display_data(content.data);
435 } else if (msg_type === "pyout") {
437 } else if (msg_type === "pyout") {
436 cell.expand();
438 cell.expand();
437 cell.append_pyout(content.data, content.execution_count)
439 cell.append_pyout(content.data, content.execution_count)
438 } else if (msg_type === "pyerr") {
440 } else if (msg_type === "pyerr") {
439 cell.expand();
441 cell.expand();
440 cell.append_pyerr(content.ename, content.evalue, content.traceback);
442 cell.append_pyerr(content.ename, content.evalue, content.traceback);
441 } else if (msg_type === "status") {
443 } else if (msg_type === "status") {
442 if (content.execution_state === "busy") {
444 if (content.execution_state === "busy") {
443 IPython.kernel_status_widget.status_busy();
445 IPython.kernel_status_widget.status_busy();
444 } else if (content.execution_state === "idle") {
446 } else if (content.execution_state === "idle") {
445 IPython.kernel_status_widget.status_idle();
447 IPython.kernel_status_widget.status_idle();
446 };
448 };
447 }
449 }
448 };
450 };
449
451
450
452
451 Notebook.prototype.kernel_started = function () {
453 Notebook.prototype.kernel_started = function () {
452 console.log("Kernel started: ", this.kernel.kernel_id);
454 console.log("Kernel started: ", this.kernel.kernel_id);
453 this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
455 this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
454 this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
456 this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
455 };
457 };
456
458
457
459
458 Notebook.prototype.execute_selected_cell = function (add_new) {
460 Notebook.prototype.execute_selected_cell = function (add_new) {
459 if (add_new === undefined) {add_new = true;};
461 if (add_new === undefined) {add_new = true;};
460 var that = this;
462 var that = this;
461 var cell = that.selected_cell();
463 var cell = that.selected_cell();
462 var cell_index = that.find_cell_index(cell);
464 var cell_index = that.find_cell_index(cell);
463 // TODO: the logic here needs to be moved into appropriate
465 // TODO: the logic here needs to be moved into appropriate
464 // methods of Notebook.
466 // methods of Notebook.
465 if (cell instanceof IPython.CodeCell) {
467 if (cell instanceof IPython.CodeCell) {
466 cell.clear_output();
468 cell.clear_output();
467 var code = cell.get_code();
469 var code = cell.get_code();
468 if (that.notebook_load_re.test(code)) {
470 if (that.notebook_load_re.test(code)) {
469 var code_parts = code.split(' ');
471 var code_parts = code.split(' ');
470 if (code_parts.length === 3) {
472 if (code_parts.length === 3) {
471 that.load_notebook(code_parts[2]);
473 that.load_notebook(code_parts[2]);
472 };
474 };
473 } else if (that.notebook_save_re.test(code)) {
475 } else if (that.notebook_save_re.test(code)) {
474 var code_parts = code.split(' ');
476 var code_parts = code.split(' ');
475 if (code_parts.length === 3) {
477 if (code_parts.length === 3) {
476 that.save_notebook(code_parts[2]);
478 that.save_notebook(code_parts[2]);
477 } else {
479 } else {
478 that.save_notebook()
480 that.save_notebook()
479 };
481 };
480 } else {
482 } else {
481 var msg_id = that.kernel.execute(cell.get_code());
483 var msg_id = that.kernel.execute(cell.get_code());
482 that.msg_cell_map[msg_id] = cell.cell_id;
484 that.msg_cell_map[msg_id] = cell.cell_id;
483 };
485 };
484 } else if (cell instanceof IPython.TextCell) {
486 } else if (cell instanceof IPython.TextCell) {
485 cell.render();
487 cell.render();
486 }
488 }
487 if ((cell_index === (that.ncells()-1)) && add_new) {
489 if ((cell_index === (that.ncells()-1)) && add_new) {
488 that.insert_code_cell_after();
490 that.insert_code_cell_after();
489 // If we are adding a new cell at the end, scroll down to show it.
491 // If we are adding a new cell at the end, scroll down to show it.
490 that.scroll_to_bottom();
492 that.scroll_to_bottom();
491 } else {
493 } else {
492 that.select(cell_index+1);
494 that.select(cell_index+1);
493 };
495 };
494 };
496 };
495
497
496
498
497 Notebook.prototype.execute_all_cells = function () {
499 Notebook.prototype.execute_all_cells = function () {
498 var ncells = this.ncells();
500 var ncells = this.ncells();
499 for (var i=0; i<ncells; i++) {
501 for (var i=0; i<ncells; i++) {
500 this.select(i);
502 this.select(i);
501 this.execute_selected_cell(false);
503 this.execute_selected_cell(false);
502 };
504 };
503 this.scroll_to_bottom();
505 this.scroll_to_bottom();
504 };
506 };
505
507
506 // Persistance and loading
508 // Persistance and loading
507
509
508
510
509 Notebook.prototype.fromJSON = function (data) {
511 Notebook.prototype.fromJSON = function (data) {
510 var ncells = this.ncells();
512 var ncells = this.ncells();
511 for (var i=0; i<ncells; i++) {
513 for (var i=0; i<ncells; i++) {
512 // Always delete cell 0 as they get renumbered as they are deleted.
514 // Always delete cell 0 as they get renumbered as they are deleted.
513 this.delete_cell(0);
515 this.delete_cell(0);
514 };
516 };
515 var new_cells = data.cells;
517 var new_cells = data.cells;
516 ncells = new_cells.length;
518 ncells = new_cells.length;
517 var cell_data = null;
519 var cell_data = null;
518 for (var i=0; i<ncells; i++) {
520 for (var i=0; i<ncells; i++) {
519 cell_data = new_cells[i];
521 cell_data = new_cells[i];
520 if (cell_data.cell_type == 'code') {
522 if (cell_data.cell_type == 'code') {
521 this.insert_code_cell_after();
523 this.insert_code_cell_after();
522 this.selected_cell().fromJSON(cell_data);
524 this.selected_cell().fromJSON(cell_data);
523 } else if (cell_data.cell_type === 'text') {
525 } else if (cell_data.cell_type === 'text') {
524 this.insert_text_cell_after();
526 this.insert_text_cell_after();
525 this.selected_cell().fromJSON(cell_data);
527 this.selected_cell().fromJSON(cell_data);
526 };
528 };
527 };
529 };
528 };
530 };
529
531
530
532
531 Notebook.prototype.toJSON = function () {
533 Notebook.prototype.toJSON = function () {
532 var cells = this.cells();
534 var cells = this.cells();
533 var ncells = cells.length;
535 var ncells = cells.length;
534 cell_array = new Array(ncells);
536 cell_array = new Array(ncells);
535 for (var i=0; i<ncells; i++) {
537 for (var i=0; i<ncells; i++) {
536 cell_array[i] = cells[i].toJSON();
538 cell_array[i] = cells[i].toJSON();
537 };
539 };
538 json = {
540 json = {
539 cells : cell_array
541 cells : cell_array
540 };
542 };
541 return json
543 return json
542 };
544 };
543
545
544
546
545 Notebook.prototype.test_filename = function (filename) {
547 Notebook.prototype.test_filename = function (filename) {
546 if (this.notebook_filename_re.test(filename)) {
548 if (this.notebook_filename_re.test(filename)) {
547 return true;
549 return true;
548 } else {
550 } else {
549 var bad_filename = $('<div/>');
551 var bad_filename = $('<div/>');
550 bad_filename.html(
552 bad_filename.html(
551 "The filename you entered (" + filename + ") is not valid. Notebook filenames must have the following form: foo.ipynb"
553 "The filename you entered (" + filename + ") is not valid. Notebook filenames must have the following form: foo.ipynb"
552 );
554 );
553 bad_filename.dialog({title: 'Invalid filename', modal: true});
555 bad_filename.dialog({title: 'Invalid filename', modal: true});
554 return false;
556 return false;
555 };
557 };
556 };
558 };
557
559
558 Notebook.prototype.save_notebook = function (filename) {
560 Notebook.prototype.save_notebook = function (filename) {
559 this.filename = filename || this.filename || '';
561 this.filename = filename || this.filename || '';
560 if (this.filename === '') {
562 if (this.filename === '') {
561 var no_filename = $('<div/>');
563 var no_filename = $('<div/>');
562 no_filename.html(
564 no_filename.html(
563 "This notebook has no filename, please specify a filename of the form: foo.ipynb"
565 "This notebook has no filename, please specify a filename of the form: foo.ipynb"
564 );
566 );
565 no_filename.dialog({title: 'Missing filename', modal: true});
567 no_filename.dialog({title: 'Missing filename', modal: true});
566 return;
568 return;
567 }
569 }
568 if (!this.test_filename(this.filename)) {return;}
570 if (!this.test_filename(this.filename)) {return;}
569 var thedata = this.toJSON();
571 var thedata = this.toJSON();
570 var settings = {
572 var settings = {
571 processData : false,
573 processData : false,
572 cache : false,
574 cache : false,
573 type : "PUT",
575 type : "PUT",
574 data : JSON.stringify(thedata),
576 data : JSON.stringify(thedata),
575 success : function (data, status, xhr) {console.log(data);}
577 success : function (data, status, xhr) {console.log(data);}
576 };
578 };
577 $.ajax("/notebooks/" + this.filename, settings);
579 $.ajax("/notebooks/" + this.filename, settings);
578 };
580 };
579
581
580
582
581 Notebook.prototype.load_notebook = function (filename) {
583 Notebook.prototype.load_notebook = function (filename) {
582 if (!this.test_filename(filename)) {return;}
584 if (!this.test_filename(filename)) {return;}
583 var that = this;
585 var that = this;
584 // We do the call with settings so we can set cache to false.
586 // We do the call with settings so we can set cache to false.
585 var settings = {
587 var settings = {
586 processData : false,
588 processData : false,
587 cache : false,
589 cache : false,
588 type : "GET",
590 type : "GET",
589 dataType : "json",
591 dataType : "json",
590 success : function (data, status, xhr) {
592 success : function (data, status, xhr) {
591 that.fromJSON(data);
593 that.fromJSON(data);
592 that.filename = filename;
594 that.filename = filename;
593 that.kernel.restart();
595 that.kernel.restart();
594 }
596 }
595 };
597 };
596 $.ajax("/notebooks/" + filename, settings);
598 $.ajax("/notebooks/" + filename, settings);
597 }
599 }
598
600
599 IPython.Notebook = Notebook;
601 IPython.Notebook = Notebook;
600
602
601 return IPython;
603 return IPython;
602
604
603 }(IPython));
605 }(IPython));
604
606
General Comments 0
You need to be logged in to leave comments. Login now