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