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