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