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