##// END OF EJS Templates
show_keyboard_shortcuts -> toggle_keyboard_shortcuts...
MinRK -
Show More
@@ -1,972 +1,985
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008-2011 The IPython Development Team
2 // Copyright (C) 2008-2011 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // Notebook
9 // Notebook
10 //============================================================================
10 //============================================================================
11
11
12 var IPython = (function (IPython) {
12 var IPython = (function (IPython) {
13
13
14 var utils = IPython.utils;
14 var utils = IPython.utils;
15
15
16 var Notebook = function (selector) {
16 var Notebook = function (selector) {
17 this.element = $(selector);
17 this.element = $(selector);
18 this.element.scroll();
18 this.element.scroll();
19 this.element.data("notebook", this);
19 this.element.data("notebook", this);
20 this.next_prompt_number = 1;
20 this.next_prompt_number = 1;
21 this.kernel = null;
21 this.kernel = null;
22 this.dirty = false;
22 this.dirty = false;
23 this.msg_cell_map = {};
23 this.msg_cell_map = {};
24 this.metadata = {};
24 this.metadata = {};
25 this.control_key_active = false;
25 this.control_key_active = false;
26 this.style();
26 this.style();
27 this.create_elements();
27 this.create_elements();
28 this.bind_events();
28 this.bind_events();
29 };
29 };
30
30
31
31
32 Notebook.prototype.style = function () {
32 Notebook.prototype.style = function () {
33 $('div#notebook').addClass('border-box-sizing');
33 $('div#notebook').addClass('border-box-sizing');
34 };
34 };
35
35
36
36
37 Notebook.prototype.create_elements = function () {
37 Notebook.prototype.create_elements = function () {
38 // We add this end_space div to the end of the notebook div to:
38 // We add this end_space div to the end of the notebook div to:
39 // i) provide a margin between the last cell and the end of the notebook
39 // i) provide a margin between the last cell and the end of the notebook
40 // ii) to prevent the div from scrolling up when the last cell is being
40 // ii) to prevent the div from scrolling up when the last cell is being
41 // edited, but is too low on the page, which browsers will do automatically.
41 // edited, but is too low on the page, which browsers will do automatically.
42 var that = this;
42 var that = this;
43 var end_space = $('<div class="end_space"></div>').height(150);
43 var end_space = $('<div class="end_space"></div>').height(150);
44 end_space.dblclick(function (e) {
44 end_space.dblclick(function (e) {
45 var ncells = that.ncells();
45 var ncells = that.ncells();
46 that.insert_code_cell_below(ncells-1);
46 that.insert_code_cell_below(ncells-1);
47 });
47 });
48 this.element.append(end_space);
48 this.element.append(end_space);
49 $('div#notebook').addClass('border-box-sizing');
49 $('div#notebook').addClass('border-box-sizing');
50 };
50 };
51
51
52
52
53 Notebook.prototype.bind_events = function () {
53 Notebook.prototype.bind_events = function () {
54 var that = this;
54 var that = this;
55 $(document).keydown(function (event) {
55 $(document).keydown(function (event) {
56 // console.log(event);
56 // console.log(event);
57 if (event.which === 38) {
57 if (event.which === 38) {
58 var cell = that.selected_cell();
58 var cell = that.selected_cell();
59 if (cell.at_top()) {
59 if (cell.at_top()) {
60 event.preventDefault();
60 event.preventDefault();
61 that.select_prev();
61 that.select_prev();
62 };
62 };
63 } else if (event.which === 40) {
63 } else if (event.which === 40) {
64 var cell = that.selected_cell();
64 var cell = that.selected_cell();
65 if (cell.at_bottom()) {
65 if (cell.at_bottom()) {
66 event.preventDefault();
66 event.preventDefault();
67 that.select_next();
67 that.select_next();
68 };
68 };
69 } else if (event.which === 13 && event.shiftKey) {
69 } else if (event.which === 13 && event.shiftKey) {
70 that.execute_selected_cell();
70 that.execute_selected_cell();
71 return false;
71 return false;
72 } else if (event.which === 13 && event.ctrlKey) {
72 } else if (event.which === 13 && event.ctrlKey) {
73 that.execute_selected_cell({terminal:true});
73 that.execute_selected_cell({terminal:true});
74 return false;
74 return false;
75 } else if (event.which === 77 && event.ctrlKey) {
75 } else if (event.which === 77 && event.ctrlKey) {
76 that.control_key_active = true;
76 that.control_key_active = true;
77 return false;
77 return false;
78 } else if (event.which === 68 && that.control_key_active) {
78 } else if (event.which === 68 && that.control_key_active) {
79 // Delete selected cell = d
79 // Delete selected cell = d
80 that.delete_cell();
80 that.delete_cell();
81 that.control_key_active = false;
81 that.control_key_active = false;
82 return false;
82 return false;
83 } else if (event.which === 65 && that.control_key_active) {
83 } else if (event.which === 65 && that.control_key_active) {
84 // Insert code cell above selected = a
84 // Insert code cell above selected = a
85 that.insert_code_cell_above();
85 that.insert_code_cell_above();
86 that.control_key_active = false;
86 that.control_key_active = false;
87 return false;
87 return false;
88 } else if (event.which === 66 && that.control_key_active) {
88 } else if (event.which === 66 && that.control_key_active) {
89 // Insert code cell below selected = b
89 // Insert code cell below selected = b
90 that.insert_code_cell_below();
90 that.insert_code_cell_below();
91 that.control_key_active = false;
91 that.control_key_active = false;
92 return false;
92 return false;
93 } else if (event.which === 67 && that.control_key_active) {
93 } else if (event.which === 67 && that.control_key_active) {
94 // To code = c
94 // To code = c
95 that.to_code();
95 that.to_code();
96 that.control_key_active = false;
96 that.control_key_active = false;
97 return false;
97 return false;
98 } else if (event.which === 77 && that.control_key_active) {
98 } else if (event.which === 77 && that.control_key_active) {
99 // To markdown = m
99 // To markdown = m
100 that.to_markdown();
100 that.to_markdown();
101 that.control_key_active = false;
101 that.control_key_active = false;
102 return false;
102 return false;
103 } else if (event.which === 84 && that.control_key_active) {
103 } else if (event.which === 84 && that.control_key_active) {
104 // Toggle output = t
104 // Toggle output = t
105 that.toggle_output();
105 that.toggle_output();
106 that.control_key_active = false;
106 that.control_key_active = false;
107 return false;
107 return false;
108 } else if (event.which === 83 && that.control_key_active) {
108 } else if (event.which === 83 && that.control_key_active) {
109 // Save notebook = s
109 // Save notebook = s
110 IPython.save_widget.save_notebook();
110 IPython.save_widget.save_notebook();
111 that.control_key_active = false;
111 that.control_key_active = false;
112 return false;
112 return false;
113 } else if (event.which === 74 && that.control_key_active) {
113 } else if (event.which === 74 && that.control_key_active) {
114 // Move cell down = j
114 // Move cell down = j
115 that.move_cell_down();
115 that.move_cell_down();
116 that.control_key_active = false;
116 that.control_key_active = false;
117 return false;
117 return false;
118 } else if (event.which === 75 && that.control_key_active) {
118 } else if (event.which === 75 && that.control_key_active) {
119 // Move cell up = k
119 // Move cell up = k
120 that.move_cell_up();
120 that.move_cell_up();
121 that.control_key_active = false;
121 that.control_key_active = false;
122 return false;
122 return false;
123 } else if (event.which === 80 && that.control_key_active) {
123 } else if (event.which === 80 && that.control_key_active) {
124 // Select previous = p
124 // Select previous = p
125 that.select_prev();
125 that.select_prev();
126 that.control_key_active = false;
126 that.control_key_active = false;
127 return false;
127 return false;
128 } else if (event.which === 78 && that.control_key_active) {
128 } else if (event.which === 78 && that.control_key_active) {
129 // Select next = n
129 // Select next = n
130 that.select_next();
130 that.select_next();
131 that.control_key_active = false;
131 that.control_key_active = false;
132 return false;
132 return false;
133 } else if (event.which === 76 && that.control_key_active) {
133 } else if (event.which === 76 && that.control_key_active) {
134 // Toggle line numbers = l
134 // Toggle line numbers = l
135 that.cell_toggle_line_numbers();
135 that.cell_toggle_line_numbers();
136 that.control_key_active = false;
136 that.control_key_active = false;
137 return false;
137 return false;
138 } else if (event.which === 73 && that.control_key_active) {
138 } else if (event.which === 73 && that.control_key_active) {
139 // Interrupt kernel = i
139 // Interrupt kernel = i
140 IPython.notebook.kernel.interrupt();
140 IPython.notebook.kernel.interrupt();
141 that.control_key_active = false;
141 that.control_key_active = false;
142 return false;
142 return false;
143 } else if (event.which === 190 && that.control_key_active) {
143 } else if (event.which === 190 && that.control_key_active) {
144 // Restart kernel = . # matches qt console
144 // Restart kernel = . # matches qt console
145 IPython.notebook.restart_kernel();
145 IPython.notebook.restart_kernel();
146 that.control_key_active = false;
146 that.control_key_active = false;
147 return false;
147 return false;
148 } else if (event.which === 72 && that.control_key_active) {
148 } else if (event.which === 72 && that.control_key_active) {
149 // Show keyboard shortcuts = h
149 // Show keyboard shortcuts = h
150 that.show_keyboard_shortcuts();
150 that.toggle_keyboard_shortcuts();
151 that.control_key_active = false;
151 that.control_key_active = false;
152 return false;
152 return false;
153 } else if (that.control_key_active) {
153 } else if (that.control_key_active) {
154 that.control_key_active = false;
154 that.control_key_active = false;
155 return true;
155 return true;
156 };
156 };
157 });
157 });
158
158
159 this.element.bind('collapse_pager', function () {
159 this.element.bind('collapse_pager', function () {
160 var app_height = $('div#main_app').height(); // content height
160 var app_height = $('div#main_app').height(); // content height
161 var splitter_height = $('div#pager_splitter').outerHeight(true);
161 var splitter_height = $('div#pager_splitter').outerHeight(true);
162 var new_height = app_height - splitter_height;
162 var new_height = app_height - splitter_height;
163 that.element.animate({height : new_height + 'px'}, 'fast');
163 that.element.animate({height : new_height + 'px'}, 'fast');
164 });
164 });
165
165
166 this.element.bind('expand_pager', function () {
166 this.element.bind('expand_pager', function () {
167 var app_height = $('div#main_app').height(); // content height
167 var app_height = $('div#main_app').height(); // content height
168 var splitter_height = $('div#pager_splitter').outerHeight(true);
168 var splitter_height = $('div#pager_splitter').outerHeight(true);
169 var pager_height = $('div#pager').outerHeight(true);
169 var pager_height = $('div#pager').outerHeight(true);
170 var new_height = app_height - pager_height - splitter_height;
170 var new_height = app_height - pager_height - splitter_height;
171 that.element.animate({height : new_height + 'px'}, 'fast');
171 that.element.animate({height : new_height + 'px'}, 'fast');
172 });
172 });
173
173
174 this.element.bind('collapse_left_panel', function () {
174 this.element.bind('collapse_left_panel', function () {
175 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
175 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
176 var new_margin = splitter_width;
176 var new_margin = splitter_width;
177 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
177 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
178 });
178 });
179
179
180 this.element.bind('expand_left_panel', function () {
180 this.element.bind('expand_left_panel', function () {
181 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
181 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
182 var left_panel_width = IPython.left_panel.width;
182 var left_panel_width = IPython.left_panel.width;
183 var new_margin = splitter_width + left_panel_width;
183 var new_margin = splitter_width + left_panel_width;
184 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
184 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
185 });
185 });
186
186
187 $(window).bind('beforeunload', function () {
187 $(window).bind('beforeunload', function () {
188 var kill_kernel = $('#kill_kernel').prop('checked');
188 var kill_kernel = $('#kill_kernel').prop('checked');
189 if (kill_kernel) {
189 if (kill_kernel) {
190 that.kernel.kill();
190 that.kernel.kill();
191 }
191 }
192 if (that.dirty) {
192 if (that.dirty) {
193 return "You have unsaved changes that will be lost if you leave this page.";
193 return "You have unsaved changes that will be lost if you leave this page.";
194 };
194 };
195 });
195 });
196 };
196 };
197
197
198
198
199 Notebook.prototype.show_keyboard_shortcuts = function () {
199 Notebook.prototype.toggle_keyboard_shortcuts = function () {
200 // toggles display of keyboard shortcut dialog
201 var that = this;
202 if ( this.shortcut_dialog ){
203 // if dialog is already shown, close it
204 this.shortcut_dialog.dialog("close");
205 this.shortcut_dialog = null;
206 return;
207 }
200 var dialog = $('<div/>');
208 var dialog = $('<div/>');
209 this.shortcut_dialog = dialog;
201 var shortcuts = [
210 var shortcuts = [
202 {key: 'Shift-Enter', help: 'run cell'},
211 {key: 'Shift-Enter', help: 'run cell'},
203 {key: 'Ctrl-Enter', help: 'run cell in-place'},
212 {key: 'Ctrl-Enter', help: 'run cell in-place'},
204 {key: 'Ctrl-m d', help: 'delete cell'},
213 {key: 'Ctrl-m d', help: 'delete cell'},
205 {key: 'Ctrl-m a', help: 'insert cell above'},
214 {key: 'Ctrl-m a', help: 'insert cell above'},
206 {key: 'Ctrl-m b', help: 'insert cell below'},
215 {key: 'Ctrl-m b', help: 'insert cell below'},
207 {key: 'Ctrl-m t', help: 'toggle output'},
216 {key: 'Ctrl-m t', help: 'toggle output'},
208 {key: 'Ctrl-m l', help: 'toggle line numbers'},
217 {key: 'Ctrl-m l', help: 'toggle line numbers'},
209 {key: 'Ctrl-m s', help: 'save notebook'},
218 {key: 'Ctrl-m s', help: 'save notebook'},
210 {key: 'Ctrl-m j', help: 'move cell down'},
219 {key: 'Ctrl-m j', help: 'move cell down'},
211 {key: 'Ctrl-m k', help: 'move cell up'},
220 {key: 'Ctrl-m k', help: 'move cell up'},
212 {key: 'Ctrl-m c', help: 'code cell'},
221 {key: 'Ctrl-m c', help: 'code cell'},
213 {key: 'Ctrl-m m', help: 'markdown cell'},
222 {key: 'Ctrl-m m', help: 'markdown cell'},
214 {key: 'Ctrl-m p', help: 'select previous'},
223 {key: 'Ctrl-m p', help: 'select previous'},
215 {key: 'Ctrl-m n', help: 'select next'},
224 {key: 'Ctrl-m n', help: 'select next'},
216 {key: 'Ctrl-m i', help: 'interrupt kernel'},
225 {key: 'Ctrl-m i', help: 'interrupt kernel'},
217 {key: 'Ctrl-m .', help: 'restart kernel'},
226 {key: 'Ctrl-m .', help: 'restart kernel'},
218 {key: 'Ctrl-m h', help: 'show keyboard shortcuts'}
227 {key: 'Ctrl-m h', help: 'show keyboard shortcuts'}
219 ];
228 ];
220 for (var i=0; i<shortcuts.length; i++) {
229 for (var i=0; i<shortcuts.length; i++) {
221 dialog.append($('<div>').
230 dialog.append($('<div>').
222 append($('<span/>').addClass('shortcut_key').html(shortcuts[i].key)).
231 append($('<span/>').addClass('shortcut_key').html(shortcuts[i].key)).
223 append($('<span/>').addClass('shortcut_descr').html(' : ' + shortcuts[i].help))
232 append($('<span/>').addClass('shortcut_descr').html(' : ' + shortcuts[i].help))
224 );
233 );
225 };
234 };
235 dialog.bind('dialogclose', function(event) {
236 // dialog has been closed, allow it to be drawn again.
237 that.shortcut_dialog = null;
238 });
226 dialog.dialog({title: 'Keyboard shortcuts'});
239 dialog.dialog({title: 'Keyboard shortcuts'});
227 };
240 };
228
241
229
242
230 Notebook.prototype.scroll_to_bottom = function () {
243 Notebook.prototype.scroll_to_bottom = function () {
231 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
244 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
232 };
245 };
233
246
234
247
235 Notebook.prototype.scroll_to_top = function () {
248 Notebook.prototype.scroll_to_top = function () {
236 this.element.animate({scrollTop:0}, 0);
249 this.element.animate({scrollTop:0}, 0);
237 };
250 };
238
251
239
252
240 // Cell indexing, retrieval, etc.
253 // Cell indexing, retrieval, etc.
241
254
242
255
243 Notebook.prototype.cell_elements = function () {
256 Notebook.prototype.cell_elements = function () {
244 return this.element.children("div.cell");
257 return this.element.children("div.cell");
245 }
258 }
246
259
247
260
248 Notebook.prototype.ncells = function (cell) {
261 Notebook.prototype.ncells = function (cell) {
249 return this.cell_elements().length;
262 return this.cell_elements().length;
250 }
263 }
251
264
252
265
253 // TODO: we are often calling cells as cells()[i], which we should optimize
266 // TODO: we are often calling cells as cells()[i], which we should optimize
254 // to cells(i) or a new method.
267 // to cells(i) or a new method.
255 Notebook.prototype.cells = function () {
268 Notebook.prototype.cells = function () {
256 return this.cell_elements().toArray().map(function (e) {
269 return this.cell_elements().toArray().map(function (e) {
257 return $(e).data("cell");
270 return $(e).data("cell");
258 });
271 });
259 }
272 }
260
273
261
274
262 Notebook.prototype.find_cell_index = function (cell) {
275 Notebook.prototype.find_cell_index = function (cell) {
263 var result = null;
276 var result = null;
264 this.cell_elements().filter(function (index) {
277 this.cell_elements().filter(function (index) {
265 if ($(this).data("cell") === cell) {
278 if ($(this).data("cell") === cell) {
266 result = index;
279 result = index;
267 };
280 };
268 });
281 });
269 return result;
282 return result;
270 };
283 };
271
284
272
285
273 Notebook.prototype.index_or_selected = function (index) {
286 Notebook.prototype.index_or_selected = function (index) {
274 return index || this.selected_index() || 0;
287 return index || this.selected_index() || 0;
275 }
288 }
276
289
277
290
278 Notebook.prototype.select = function (index) {
291 Notebook.prototype.select = function (index) {
279 if (index !== undefined && index >= 0 && index < this.ncells()) {
292 if (index !== undefined && index >= 0 && index < this.ncells()) {
280 if (this.selected_index() !== null) {
293 if (this.selected_index() !== null) {
281 this.selected_cell().unselect();
294 this.selected_cell().unselect();
282 };
295 };
283 this.cells()[index].select();
296 this.cells()[index].select();
284 };
297 };
285 return this;
298 return this;
286 };
299 };
287
300
288
301
289 Notebook.prototype.select_next = function () {
302 Notebook.prototype.select_next = function () {
290 var index = this.selected_index();
303 var index = this.selected_index();
291 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
304 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
292 this.select(index+1);
305 this.select(index+1);
293 };
306 };
294 return this;
307 return this;
295 };
308 };
296
309
297
310
298 Notebook.prototype.select_prev = function () {
311 Notebook.prototype.select_prev = function () {
299 var index = this.selected_index();
312 var index = this.selected_index();
300 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
313 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
301 this.select(index-1);
314 this.select(index-1);
302 };
315 };
303 return this;
316 return this;
304 };
317 };
305
318
306
319
307 Notebook.prototype.selected_index = function () {
320 Notebook.prototype.selected_index = function () {
308 var result = null;
321 var result = null;
309 this.cell_elements().filter(function (index) {
322 this.cell_elements().filter(function (index) {
310 if ($(this).data("cell").selected === true) {
323 if ($(this).data("cell").selected === true) {
311 result = index;
324 result = index;
312 };
325 };
313 });
326 });
314 return result;
327 return result;
315 };
328 };
316
329
317
330
318 Notebook.prototype.cell_for_msg = function (msg_id) {
331 Notebook.prototype.cell_for_msg = function (msg_id) {
319 var cell_id = this.msg_cell_map[msg_id];
332 var cell_id = this.msg_cell_map[msg_id];
320 var result = null;
333 var result = null;
321 this.cell_elements().filter(function (index) {
334 this.cell_elements().filter(function (index) {
322 cell = $(this).data("cell");
335 cell = $(this).data("cell");
323 if (cell.cell_id === cell_id) {
336 if (cell.cell_id === cell_id) {
324 result = cell;
337 result = cell;
325 };
338 };
326 });
339 });
327 return result;
340 return result;
328 };
341 };
329
342
330
343
331 Notebook.prototype.selected_cell = function () {
344 Notebook.prototype.selected_cell = function () {
332 return this.cell_elements().eq(this.selected_index()).data("cell");
345 return this.cell_elements().eq(this.selected_index()).data("cell");
333 }
346 }
334
347
335
348
336 // Cell insertion, deletion and moving.
349 // Cell insertion, deletion and moving.
337
350
338
351
339 Notebook.prototype.delete_cell = function (index) {
352 Notebook.prototype.delete_cell = function (index) {
340 var i = index || this.selected_index();
353 var i = index || this.selected_index();
341 if (i !== null && i >= 0 && i < this.ncells()) {
354 if (i !== null && i >= 0 && i < this.ncells()) {
342 this.cell_elements().eq(i).remove();
355 this.cell_elements().eq(i).remove();
343 if (i === (this.ncells())) {
356 if (i === (this.ncells())) {
344 this.select(i-1);
357 this.select(i-1);
345 } else {
358 } else {
346 this.select(i);
359 this.select(i);
347 };
360 };
348 };
361 };
349 this.dirty = true;
362 this.dirty = true;
350 return this;
363 return this;
351 };
364 };
352
365
353
366
354 Notebook.prototype.append_cell = function (cell) {
367 Notebook.prototype.append_cell = function (cell) {
355 this.element.find('div.end_space').before(cell.element);
368 this.element.find('div.end_space').before(cell.element);
356 this.dirty = true;
369 this.dirty = true;
357 return this;
370 return this;
358 };
371 };
359
372
360
373
361 Notebook.prototype.insert_cell_below = function (cell, index) {
374 Notebook.prototype.insert_cell_below = function (cell, index) {
362 var ncells = this.ncells();
375 var ncells = this.ncells();
363 if (ncells === 0) {
376 if (ncells === 0) {
364 this.append_cell(cell);
377 this.append_cell(cell);
365 return this;
378 return this;
366 };
379 };
367 if (index >= 0 && index < ncells) {
380 if (index >= 0 && index < ncells) {
368 this.cell_elements().eq(index).after(cell.element);
381 this.cell_elements().eq(index).after(cell.element);
369 };
382 };
370 this.dirty = true;
383 this.dirty = true;
371 return this
384 return this
372 };
385 };
373
386
374
387
375 Notebook.prototype.insert_cell_above = function (cell, index) {
388 Notebook.prototype.insert_cell_above = function (cell, index) {
376 var ncells = this.ncells();
389 var ncells = this.ncells();
377 if (ncells === 0) {
390 if (ncells === 0) {
378 this.append_cell(cell);
391 this.append_cell(cell);
379 return this;
392 return this;
380 };
393 };
381 if (index >= 0 && index < ncells) {
394 if (index >= 0 && index < ncells) {
382 this.cell_elements().eq(index).before(cell.element);
395 this.cell_elements().eq(index).before(cell.element);
383 };
396 };
384 this.dirty = true;
397 this.dirty = true;
385 return this;
398 return this;
386 };
399 };
387
400
388
401
389 Notebook.prototype.move_cell_up = function (index) {
402 Notebook.prototype.move_cell_up = function (index) {
390 var i = index || this.selected_index();
403 var i = index || this.selected_index();
391 if (i !== null && i < this.ncells() && i > 0) {
404 if (i !== null && i < this.ncells() && i > 0) {
392 var pivot = this.cell_elements().eq(i-1);
405 var pivot = this.cell_elements().eq(i-1);
393 var tomove = this.cell_elements().eq(i);
406 var tomove = this.cell_elements().eq(i);
394 if (pivot !== null && tomove !== null) {
407 if (pivot !== null && tomove !== null) {
395 tomove.detach();
408 tomove.detach();
396 pivot.before(tomove);
409 pivot.before(tomove);
397 this.select(i-1);
410 this.select(i-1);
398 };
411 };
399 };
412 };
400 this.dirty = true;
413 this.dirty = true;
401 return this;
414 return this;
402 }
415 }
403
416
404
417
405 Notebook.prototype.move_cell_down = function (index) {
418 Notebook.prototype.move_cell_down = function (index) {
406 var i = index || this.selected_index();
419 var i = index || this.selected_index();
407 if (i !== null && i < (this.ncells()-1) && i >= 0) {
420 if (i !== null && i < (this.ncells()-1) && i >= 0) {
408 var pivot = this.cell_elements().eq(i+1)
421 var pivot = this.cell_elements().eq(i+1)
409 var tomove = this.cell_elements().eq(i)
422 var tomove = this.cell_elements().eq(i)
410 if (pivot !== null && tomove !== null) {
423 if (pivot !== null && tomove !== null) {
411 tomove.detach();
424 tomove.detach();
412 pivot.after(tomove);
425 pivot.after(tomove);
413 this.select(i+1);
426 this.select(i+1);
414 };
427 };
415 };
428 };
416 this.dirty = true;
429 this.dirty = true;
417 return this;
430 return this;
418 }
431 }
419
432
420
433
421 Notebook.prototype.sort_cells = function () {
434 Notebook.prototype.sort_cells = function () {
422 var ncells = this.ncells();
435 var ncells = this.ncells();
423 var sindex = this.selected_index();
436 var sindex = this.selected_index();
424 var swapped;
437 var swapped;
425 do {
438 do {
426 swapped = false
439 swapped = false
427 for (var i=1; i<ncells; i++) {
440 for (var i=1; i<ncells; i++) {
428 current = this.cell_elements().eq(i).data("cell");
441 current = this.cell_elements().eq(i).data("cell");
429 previous = this.cell_elements().eq(i-1).data("cell");
442 previous = this.cell_elements().eq(i-1).data("cell");
430 if (previous.input_prompt_number > current.input_prompt_number) {
443 if (previous.input_prompt_number > current.input_prompt_number) {
431 this.move_cell_up(i);
444 this.move_cell_up(i);
432 swapped = true;
445 swapped = true;
433 };
446 };
434 };
447 };
435 } while (swapped);
448 } while (swapped);
436 this.select(sindex);
449 this.select(sindex);
437 return this;
450 return this;
438 };
451 };
439
452
440
453
441 Notebook.prototype.insert_code_cell_above = function (index) {
454 Notebook.prototype.insert_code_cell_above = function (index) {
442 // TODO: Bounds check for i
455 // TODO: Bounds check for i
443 var i = this.index_or_selected(index);
456 var i = this.index_or_selected(index);
444 var cell = new IPython.CodeCell(this);
457 var cell = new IPython.CodeCell(this);
445 cell.set_input_prompt();
458 cell.set_input_prompt();
446 this.insert_cell_above(cell, i);
459 this.insert_cell_above(cell, i);
447 this.select(this.find_cell_index(cell));
460 this.select(this.find_cell_index(cell));
448 return cell;
461 return cell;
449 }
462 }
450
463
451
464
452 Notebook.prototype.insert_code_cell_below = function (index) {
465 Notebook.prototype.insert_code_cell_below = function (index) {
453 // TODO: Bounds check for i
466 // TODO: Bounds check for i
454 var i = this.index_or_selected(index);
467 var i = this.index_or_selected(index);
455 var cell = new IPython.CodeCell(this);
468 var cell = new IPython.CodeCell(this);
456 cell.set_input_prompt();
469 cell.set_input_prompt();
457 this.insert_cell_below(cell, i);
470 this.insert_cell_below(cell, i);
458 this.select(this.find_cell_index(cell));
471 this.select(this.find_cell_index(cell));
459 return cell;
472 return cell;
460 }
473 }
461
474
462
475
463 Notebook.prototype.insert_html_cell_above = function (index) {
476 Notebook.prototype.insert_html_cell_above = function (index) {
464 // TODO: Bounds check for i
477 // TODO: Bounds check for i
465 var i = this.index_or_selected(index);
478 var i = this.index_or_selected(index);
466 var cell = new IPython.HTMLCell(this);
479 var cell = new IPython.HTMLCell(this);
467 cell.config_mathjax();
480 cell.config_mathjax();
468 this.insert_cell_above(cell, i);
481 this.insert_cell_above(cell, i);
469 this.select(this.find_cell_index(cell));
482 this.select(this.find_cell_index(cell));
470 return cell;
483 return cell;
471 }
484 }
472
485
473
486
474 Notebook.prototype.insert_html_cell_below = function (index) {
487 Notebook.prototype.insert_html_cell_below = function (index) {
475 // TODO: Bounds check for i
488 // TODO: Bounds check for i
476 var i = this.index_or_selected(index);
489 var i = this.index_or_selected(index);
477 var cell = new IPython.HTMLCell(this);
490 var cell = new IPython.HTMLCell(this);
478 cell.config_mathjax();
491 cell.config_mathjax();
479 this.insert_cell_below(cell, i);
492 this.insert_cell_below(cell, i);
480 this.select(this.find_cell_index(cell));
493 this.select(this.find_cell_index(cell));
481 return cell;
494 return cell;
482 }
495 }
483
496
484
497
485 Notebook.prototype.insert_markdown_cell_above = function (index) {
498 Notebook.prototype.insert_markdown_cell_above = function (index) {
486 // TODO: Bounds check for i
499 // TODO: Bounds check for i
487 var i = this.index_or_selected(index);
500 var i = this.index_or_selected(index);
488 var cell = new IPython.MarkdownCell(this);
501 var cell = new IPython.MarkdownCell(this);
489 cell.config_mathjax();
502 cell.config_mathjax();
490 this.insert_cell_above(cell, i);
503 this.insert_cell_above(cell, i);
491 this.select(this.find_cell_index(cell));
504 this.select(this.find_cell_index(cell));
492 return cell;
505 return cell;
493 }
506 }
494
507
495
508
496 Notebook.prototype.insert_markdown_cell_below = function (index) {
509 Notebook.prototype.insert_markdown_cell_below = function (index) {
497 // TODO: Bounds check for i
510 // TODO: Bounds check for i
498 var i = this.index_or_selected(index);
511 var i = this.index_or_selected(index);
499 var cell = new IPython.MarkdownCell(this);
512 var cell = new IPython.MarkdownCell(this);
500 cell.config_mathjax();
513 cell.config_mathjax();
501 this.insert_cell_below(cell, i);
514 this.insert_cell_below(cell, i);
502 this.select(this.find_cell_index(cell));
515 this.select(this.find_cell_index(cell));
503 return cell;
516 return cell;
504 }
517 }
505
518
506
519
507 Notebook.prototype.to_code = function (index) {
520 Notebook.prototype.to_code = function (index) {
508 // TODO: Bounds check for i
521 // TODO: Bounds check for i
509 var i = this.index_or_selected(index);
522 var i = this.index_or_selected(index);
510 var source_element = this.cell_elements().eq(i);
523 var source_element = this.cell_elements().eq(i);
511 var source_cell = source_element.data("cell");
524 var source_cell = source_element.data("cell");
512 if (source_cell instanceof IPython.HTMLCell ||
525 if (source_cell instanceof IPython.HTMLCell ||
513 source_cell instanceof IPython.MarkdownCell) {
526 source_cell instanceof IPython.MarkdownCell) {
514 this.insert_code_cell_below(i);
527 this.insert_code_cell_below(i);
515 var target_cell = this.cells()[i+1];
528 var target_cell = this.cells()[i+1];
516 target_cell.set_code(source_cell.get_source());
529 target_cell.set_code(source_cell.get_source());
517 source_element.remove();
530 source_element.remove();
518 target_cell.select();
531 target_cell.select();
519 };
532 };
520 this.dirty = true;
533 this.dirty = true;
521 };
534 };
522
535
523
536
524 Notebook.prototype.to_markdown = function (index) {
537 Notebook.prototype.to_markdown = function (index) {
525 // TODO: Bounds check for i
538 // TODO: Bounds check for i
526 var i = this.index_or_selected(index);
539 var i = this.index_or_selected(index);
527 var source_element = this.cell_elements().eq(i);
540 var source_element = this.cell_elements().eq(i);
528 var source_cell = source_element.data("cell");
541 var source_cell = source_element.data("cell");
529 var target_cell = null;
542 var target_cell = null;
530 if (source_cell instanceof IPython.CodeCell) {
543 if (source_cell instanceof IPython.CodeCell) {
531 this.insert_markdown_cell_below(i);
544 this.insert_markdown_cell_below(i);
532 var target_cell = this.cells()[i+1];
545 var target_cell = this.cells()[i+1];
533 var text = source_cell.get_code();
546 var text = source_cell.get_code();
534 } else if (source_cell instanceof IPython.HTMLCell) {
547 } else if (source_cell instanceof IPython.HTMLCell) {
535 this.insert_markdown_cell_below(i);
548 this.insert_markdown_cell_below(i);
536 var target_cell = this.cells()[i+1];
549 var target_cell = this.cells()[i+1];
537 var text = source_cell.get_source();
550 var text = source_cell.get_source();
538 if (text === source_cell.placeholder) {
551 if (text === source_cell.placeholder) {
539 text = target_cell.placeholder;
552 text = target_cell.placeholder;
540 }
553 }
541 }
554 }
542 if (target_cell !== null) {
555 if (target_cell !== null) {
543 if (text === "") {text = target_cell.placeholder;};
556 if (text === "") {text = target_cell.placeholder;};
544 target_cell.set_source(text);
557 target_cell.set_source(text);
545 source_element.remove();
558 source_element.remove();
546 target_cell.edit();
559 target_cell.edit();
547 }
560 }
548 this.dirty = true;
561 this.dirty = true;
549 };
562 };
550
563
551
564
552 Notebook.prototype.to_html = function (index) {
565 Notebook.prototype.to_html = function (index) {
553 // TODO: Bounds check for i
566 // TODO: Bounds check for i
554 var i = this.index_or_selected(index);
567 var i = this.index_or_selected(index);
555 var source_element = this.cell_elements().eq(i);
568 var source_element = this.cell_elements().eq(i);
556 var source_cell = source_element.data("cell");
569 var source_cell = source_element.data("cell");
557 var target_cell = null;
570 var target_cell = null;
558 if (source_cell instanceof IPython.CodeCell) {
571 if (source_cell instanceof IPython.CodeCell) {
559 this.insert_html_cell_below(i);
572 this.insert_html_cell_below(i);
560 var target_cell = this.cells()[i+1];
573 var target_cell = this.cells()[i+1];
561 var text = source_cell.get_code();
574 var text = source_cell.get_code();
562 } else if (source_cell instanceof IPython.MarkdownCell) {
575 } else if (source_cell instanceof IPython.MarkdownCell) {
563 this.insert_html_cell_below(i);
576 this.insert_html_cell_below(i);
564 var target_cell = this.cells()[i+1];
577 var target_cell = this.cells()[i+1];
565 var text = source_cell.get_source();
578 var text = source_cell.get_source();
566 if (text === source_cell.placeholder) {
579 if (text === source_cell.placeholder) {
567 text = target_cell.placeholder;
580 text = target_cell.placeholder;
568 }
581 }
569 }
582 }
570 if (target_cell !== null) {
583 if (target_cell !== null) {
571 if (text === "") {text = target_cell.placeholder;};
584 if (text === "") {text = target_cell.placeholder;};
572 target_cell.set_source(text);
585 target_cell.set_source(text);
573 source_element.remove();
586 source_element.remove();
574 target_cell.edit();
587 target_cell.edit();
575 }
588 }
576 this.dirty = true;
589 this.dirty = true;
577 };
590 };
578
591
579
592
580 // Cell collapsing and output clearing
593 // Cell collapsing and output clearing
581
594
582 Notebook.prototype.collapse = function (index) {
595 Notebook.prototype.collapse = function (index) {
583 var i = this.index_or_selected(index);
596 var i = this.index_or_selected(index);
584 this.cells()[i].collapse();
597 this.cells()[i].collapse();
585 this.dirty = true;
598 this.dirty = true;
586 };
599 };
587
600
588
601
589 Notebook.prototype.expand = function (index) {
602 Notebook.prototype.expand = function (index) {
590 var i = this.index_or_selected(index);
603 var i = this.index_or_selected(index);
591 this.cells()[i].expand();
604 this.cells()[i].expand();
592 this.dirty = true;
605 this.dirty = true;
593 };
606 };
594
607
595
608
596 Notebook.prototype.toggle_output = function (index) {
609 Notebook.prototype.toggle_output = function (index) {
597 var i = this.index_or_selected(index);
610 var i = this.index_or_selected(index);
598 this.cells()[i].toggle_output();
611 this.cells()[i].toggle_output();
599 this.dirty = true;
612 this.dirty = true;
600 };
613 };
601
614
602
615
603 Notebook.prototype.set_autoindent = function (state) {
616 Notebook.prototype.set_autoindent = function (state) {
604 var cells = this.cells();
617 var cells = this.cells();
605 len = cells.length;
618 len = cells.length;
606 for (var i=0; i<len; i++) {
619 for (var i=0; i<len; i++) {
607 cells[i].set_autoindent(state)
620 cells[i].set_autoindent(state)
608 };
621 };
609 };
622 };
610
623
611
624
612 Notebook.prototype.clear_all_output = function () {
625 Notebook.prototype.clear_all_output = function () {
613 var ncells = this.ncells();
626 var ncells = this.ncells();
614 var cells = this.cells();
627 var cells = this.cells();
615 for (var i=0; i<ncells; i++) {
628 for (var i=0; i<ncells; i++) {
616 if (cells[i] instanceof IPython.CodeCell) {
629 if (cells[i] instanceof IPython.CodeCell) {
617 cells[i].clear_output();
630 cells[i].clear_output();
618 }
631 }
619 };
632 };
620 this.dirty = true;
633 this.dirty = true;
621 };
634 };
622
635
623 // Other cell functions: line numbers, ...
636 // Other cell functions: line numbers, ...
624
637
625 Notebook.prototype.cell_toggle_line_numbers = function() {
638 Notebook.prototype.cell_toggle_line_numbers = function() {
626 this.selected_cell().toggle_line_numbers()
639 this.selected_cell().toggle_line_numbers()
627 };
640 };
628
641
629 // Kernel related things
642 // Kernel related things
630
643
631 Notebook.prototype.start_kernel = function () {
644 Notebook.prototype.start_kernel = function () {
632 this.kernel = new IPython.Kernel();
645 this.kernel = new IPython.Kernel();
633 var notebook_id = IPython.save_widget.get_notebook_id();
646 var notebook_id = IPython.save_widget.get_notebook_id();
634 this.kernel.start(notebook_id, $.proxy(this.kernel_started, this));
647 this.kernel.start(notebook_id, $.proxy(this.kernel_started, this));
635 };
648 };
636
649
637
650
638 Notebook.prototype.restart_kernel = function () {
651 Notebook.prototype.restart_kernel = function () {
639 var that = this;
652 var that = this;
640 var notebook_id = IPython.save_widget.get_notebook_id();
653 var notebook_id = IPython.save_widget.get_notebook_id();
641
654
642 var dialog = $('<div/>');
655 var dialog = $('<div/>');
643 dialog.html('Do you want to restart the current kernel? You will lose all variables defined in it.');
656 dialog.html('Do you want to restart the current kernel? You will lose all variables defined in it.');
644 $(document).append(dialog);
657 $(document).append(dialog);
645 dialog.dialog({
658 dialog.dialog({
646 resizable: false,
659 resizable: false,
647 modal: true,
660 modal: true,
648 title: "Restart kernel or continue running?",
661 title: "Restart kernel or continue running?",
649 buttons : {
662 buttons : {
650 "Restart": function () {
663 "Restart": function () {
651 that.kernel.restart($.proxy(that.kernel_started, that));
664 that.kernel.restart($.proxy(that.kernel_started, that));
652 $(this).dialog('close');
665 $(this).dialog('close');
653 },
666 },
654 "Continue running": function () {
667 "Continue running": function () {
655 $(this).dialog('close');
668 $(this).dialog('close');
656 }
669 }
657 }
670 }
658 });
671 });
659 };
672 };
660
673
661
674
662 Notebook.prototype.kernel_started = function () {
675 Notebook.prototype.kernel_started = function () {
663 console.log("Kernel started: ", this.kernel.kernel_id);
676 console.log("Kernel started: ", this.kernel.kernel_id);
664 this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
677 this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
665 this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
678 this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
666 };
679 };
667
680
668
681
669 Notebook.prototype.handle_shell_reply = function (e) {
682 Notebook.prototype.handle_shell_reply = function (e) {
670 reply = $.parseJSON(e.data);
683 reply = $.parseJSON(e.data);
671 var header = reply.header;
684 var header = reply.header;
672 var content = reply.content;
685 var content = reply.content;
673 var msg_type = header.msg_type;
686 var msg_type = header.msg_type;
674 // console.log(reply);
687 // console.log(reply);
675 var cell = this.cell_for_msg(reply.parent_header.msg_id);
688 var cell = this.cell_for_msg(reply.parent_header.msg_id);
676 if (msg_type === "execute_reply") {
689 if (msg_type === "execute_reply") {
677 cell.set_input_prompt(content.execution_count);
690 cell.set_input_prompt(content.execution_count);
678 this.dirty = true;
691 this.dirty = true;
679 } else if (msg_type === "complete_reply") {
692 } else if (msg_type === "complete_reply") {
680 cell.finish_completing(content.matched_text, content.matches);
693 cell.finish_completing(content.matched_text, content.matches);
681 };
694 };
682 var payload = content.payload || [];
695 var payload = content.payload || [];
683 this.handle_payload(cell, payload);
696 this.handle_payload(cell, payload);
684 };
697 };
685
698
686
699
687 Notebook.prototype.handle_payload = function (cell, payload) {
700 Notebook.prototype.handle_payload = function (cell, payload) {
688 var l = payload.length;
701 var l = payload.length;
689 for (var i=0; i<l; i++) {
702 for (var i=0; i<l; i++) {
690 if (payload[i].source === 'IPython.zmq.page.page') {
703 if (payload[i].source === 'IPython.zmq.page.page') {
691 if (payload[i].text.trim() !== '') {
704 if (payload[i].text.trim() !== '') {
692 IPython.pager.clear();
705 IPython.pager.clear();
693 IPython.pager.expand();
706 IPython.pager.expand();
694 IPython.pager.append_text(payload[i].text);
707 IPython.pager.append_text(payload[i].text);
695 }
708 }
696 } else if (payload[i].source === 'IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input') {
709 } else if (payload[i].source === 'IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input') {
697 var index = this.find_cell_index(cell);
710 var index = this.find_cell_index(cell);
698 var new_cell = this.insert_code_cell_below(index);
711 var new_cell = this.insert_code_cell_below(index);
699 new_cell.set_code(payload[i].text);
712 new_cell.set_code(payload[i].text);
700 this.dirty = true;
713 this.dirty = true;
701 }
714 }
702 };
715 };
703 };
716 };
704
717
705
718
706 Notebook.prototype.handle_iopub_reply = function (e) {
719 Notebook.prototype.handle_iopub_reply = function (e) {
707 reply = $.parseJSON(e.data);
720 reply = $.parseJSON(e.data);
708 var content = reply.content;
721 var content = reply.content;
709 // console.log(reply);
722 // console.log(reply);
710 var msg_type = reply.header.msg_type;
723 var msg_type = reply.header.msg_type;
711 var cell = this.cell_for_msg(reply.parent_header.msg_id);
724 var cell = this.cell_for_msg(reply.parent_header.msg_id);
712 var output_types = ['stream','display_data','pyout','pyerr'];
725 var output_types = ['stream','display_data','pyout','pyerr'];
713 if (output_types.indexOf(msg_type) >= 0) {
726 if (output_types.indexOf(msg_type) >= 0) {
714 this.handle_output(cell, msg_type, content);
727 this.handle_output(cell, msg_type, content);
715 } else if (msg_type === 'status') {
728 } else if (msg_type === 'status') {
716 if (content.execution_state === 'busy') {
729 if (content.execution_state === 'busy') {
717 IPython.kernel_status_widget.status_busy();
730 IPython.kernel_status_widget.status_busy();
718 } else if (content.execution_state === 'idle') {
731 } else if (content.execution_state === 'idle') {
719 IPython.kernel_status_widget.status_idle();
732 IPython.kernel_status_widget.status_idle();
720 } else if (content.execution_state === 'dead') {
733 } else if (content.execution_state === 'dead') {
721 this.handle_status_dead();
734 this.handle_status_dead();
722 };
735 };
723 }
736 }
724 };
737 };
725
738
726
739
727 Notebook.prototype.handle_status_dead = function () {
740 Notebook.prototype.handle_status_dead = function () {
728 var that = this;
741 var that = this;
729 this.kernel.stop_channels();
742 this.kernel.stop_channels();
730 var dialog = $('<div/>');
743 var dialog = $('<div/>');
731 dialog.html('The kernel has died, would you like to restart it? If you do not restart the kernel, you will be able to save the notebook, but running code will not work until the notebook is reopened.');
744 dialog.html('The kernel has died, would you like to restart it? If you do not restart the kernel, you will be able to save the notebook, but running code will not work until the notebook is reopened.');
732 $(document).append(dialog);
745 $(document).append(dialog);
733 dialog.dialog({
746 dialog.dialog({
734 resizable: false,
747 resizable: false,
735 modal: true,
748 modal: true,
736 title: "Dead kernel",
749 title: "Dead kernel",
737 buttons : {
750 buttons : {
738 "Restart": function () {
751 "Restart": function () {
739 that.start_kernel();
752 that.start_kernel();
740 $(this).dialog('close');
753 $(this).dialog('close');
741 },
754 },
742 "Continue running": function () {
755 "Continue running": function () {
743 $(this).dialog('close');
756 $(this).dialog('close');
744 }
757 }
745 }
758 }
746 });
759 });
747 };
760 };
748
761
749
762
750 Notebook.prototype.handle_output = function (cell, msg_type, content) {
763 Notebook.prototype.handle_output = function (cell, msg_type, content) {
751 var json = {};
764 var json = {};
752 json.output_type = msg_type;
765 json.output_type = msg_type;
753 if (msg_type === "stream") {
766 if (msg_type === "stream") {
754 json.text = utils.fixConsole(content.data);
767 json.text = utils.fixConsole(content.data);
755 json.stream = content.name;
768 json.stream = content.name;
756 } else if (msg_type === "display_data") {
769 } else if (msg_type === "display_data") {
757 json = this.convert_mime_types(json, content.data);
770 json = this.convert_mime_types(json, content.data);
758 } else if (msg_type === "pyout") {
771 } else if (msg_type === "pyout") {
759 json.prompt_number = content.execution_count;
772 json.prompt_number = content.execution_count;
760 json = this.convert_mime_types(json, content.data);
773 json = this.convert_mime_types(json, content.data);
761 } else if (msg_type === "pyerr") {
774 } else if (msg_type === "pyerr") {
762 json.ename = content.ename;
775 json.ename = content.ename;
763 json.evalue = content.evalue;
776 json.evalue = content.evalue;
764 var traceback = [];
777 var traceback = [];
765 for (var i=0; i<content.traceback.length; i++) {
778 for (var i=0; i<content.traceback.length; i++) {
766 traceback.push(utils.fixConsole(content.traceback[i]));
779 traceback.push(utils.fixConsole(content.traceback[i]));
767 }
780 }
768 json.traceback = traceback;
781 json.traceback = traceback;
769 };
782 };
770 cell.append_output(json);
783 cell.append_output(json);
771 this.dirty = true;
784 this.dirty = true;
772 };
785 };
773
786
774
787
775 Notebook.prototype.convert_mime_types = function (json, data) {
788 Notebook.prototype.convert_mime_types = function (json, data) {
776 if (data['text/plain'] !== undefined) {
789 if (data['text/plain'] !== undefined) {
777 json.text = utils.fixConsole(data['text/plain']);
790 json.text = utils.fixConsole(data['text/plain']);
778 };
791 };
779 if (data['text/html'] !== undefined) {
792 if (data['text/html'] !== undefined) {
780 json.html = data['text/html'];
793 json.html = data['text/html'];
781 };
794 };
782 if (data['image/svg+xml'] !== undefined) {
795 if (data['image/svg+xml'] !== undefined) {
783 json.svg = data['image/svg+xml'];
796 json.svg = data['image/svg+xml'];
784 };
797 };
785 if (data['image/png'] !== undefined) {
798 if (data['image/png'] !== undefined) {
786 json.png = data['image/png'];
799 json.png = data['image/png'];
787 };
800 };
788 if (data['image/jpeg'] !== undefined) {
801 if (data['image/jpeg'] !== undefined) {
789 json.jpeg = data['image/jpeg'];
802 json.jpeg = data['image/jpeg'];
790 };
803 };
791 if (data['text/latex'] !== undefined) {
804 if (data['text/latex'] !== undefined) {
792 json.latex = data['text/latex'];
805 json.latex = data['text/latex'];
793 };
806 };
794 if (data['application/json'] !== undefined) {
807 if (data['application/json'] !== undefined) {
795 json.json = data['application/json'];
808 json.json = data['application/json'];
796 };
809 };
797 if (data['application/javascript'] !== undefined) {
810 if (data['application/javascript'] !== undefined) {
798 json.javascript = data['application/javascript'];
811 json.javascript = data['application/javascript'];
799 }
812 }
800 return json;
813 return json;
801 };
814 };
802
815
803
816
804 Notebook.prototype.execute_selected_cell = function (options) {
817 Notebook.prototype.execute_selected_cell = function (options) {
805 // add_new: should a new cell be added if we are at the end of the nb
818 // add_new: should a new cell be added if we are at the end of the nb
806 // terminal: execute in terminal mode, which stays in the current cell
819 // terminal: execute in terminal mode, which stays in the current cell
807 default_options = {terminal: false, add_new: true}
820 default_options = {terminal: false, add_new: true}
808 $.extend(default_options, options)
821 $.extend(default_options, options)
809 var that = this;
822 var that = this;
810 var cell = that.selected_cell();
823 var cell = that.selected_cell();
811 var cell_index = that.find_cell_index(cell);
824 var cell_index = that.find_cell_index(cell);
812 if (cell instanceof IPython.CodeCell) {
825 if (cell instanceof IPython.CodeCell) {
813 cell.clear_output();
826 cell.clear_output();
814 var code = cell.get_code();
827 var code = cell.get_code();
815 var msg_id = that.kernel.execute(cell.get_code());
828 var msg_id = that.kernel.execute(cell.get_code());
816 that.msg_cell_map[msg_id] = cell.cell_id;
829 that.msg_cell_map[msg_id] = cell.cell_id;
817 } else if (cell instanceof IPython.HTMLCell) {
830 } else if (cell instanceof IPython.HTMLCell) {
818 cell.render();
831 cell.render();
819 }
832 }
820 if (default_options.terminal) {
833 if (default_options.terminal) {
821 cell.select_all();
834 cell.select_all();
822 } else {
835 } else {
823 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
836 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
824 that.insert_code_cell_below();
837 that.insert_code_cell_below();
825 // If we are adding a new cell at the end, scroll down to show it.
838 // If we are adding a new cell at the end, scroll down to show it.
826 that.scroll_to_bottom();
839 that.scroll_to_bottom();
827 } else {
840 } else {
828 that.select(cell_index+1);
841 that.select(cell_index+1);
829 };
842 };
830 };
843 };
831 this.dirty = true;
844 this.dirty = true;
832 };
845 };
833
846
834
847
835 Notebook.prototype.execute_all_cells = function () {
848 Notebook.prototype.execute_all_cells = function () {
836 var ncells = this.ncells();
849 var ncells = this.ncells();
837 for (var i=0; i<ncells; i++) {
850 for (var i=0; i<ncells; i++) {
838 this.select(i);
851 this.select(i);
839 this.execute_selected_cell({add_new:false});
852 this.execute_selected_cell({add_new:false});
840 };
853 };
841 this.scroll_to_bottom();
854 this.scroll_to_bottom();
842 };
855 };
843
856
844
857
845 Notebook.prototype.complete_cell = function (cell, line, cursor_pos) {
858 Notebook.prototype.complete_cell = function (cell, line, cursor_pos) {
846 var msg_id = this.kernel.complete(line, cursor_pos);
859 var msg_id = this.kernel.complete(line, cursor_pos);
847 this.msg_cell_map[msg_id] = cell.cell_id;
860 this.msg_cell_map[msg_id] = cell.cell_id;
848 };
861 };
849
862
850 // Persistance and loading
863 // Persistance and loading
851
864
852
865
853 Notebook.prototype.fromJSON = function (data) {
866 Notebook.prototype.fromJSON = function (data) {
854 var ncells = this.ncells();
867 var ncells = this.ncells();
855 for (var i=0; i<ncells; i++) {
868 for (var i=0; i<ncells; i++) {
856 // Always delete cell 0 as they get renumbered as they are deleted.
869 // Always delete cell 0 as they get renumbered as they are deleted.
857 this.delete_cell(0);
870 this.delete_cell(0);
858 };
871 };
859 // Save the metadata
872 // Save the metadata
860 this.metadata = data.metadata;
873 this.metadata = data.metadata;
861 // Only handle 1 worksheet for now.
874 // Only handle 1 worksheet for now.
862 var worksheet = data.worksheets[0];
875 var worksheet = data.worksheets[0];
863 if (worksheet !== undefined) {
876 if (worksheet !== undefined) {
864 var new_cells = worksheet.cells;
877 var new_cells = worksheet.cells;
865 ncells = new_cells.length;
878 ncells = new_cells.length;
866 var cell_data = null;
879 var cell_data = null;
867 var new_cell = null;
880 var new_cell = null;
868 for (var i=0; i<ncells; i++) {
881 for (var i=0; i<ncells; i++) {
869 cell_data = new_cells[i];
882 cell_data = new_cells[i];
870 if (cell_data.cell_type == 'code') {
883 if (cell_data.cell_type == 'code') {
871 new_cell = this.insert_code_cell_below();
884 new_cell = this.insert_code_cell_below();
872 new_cell.fromJSON(cell_data);
885 new_cell.fromJSON(cell_data);
873 } else if (cell_data.cell_type === 'html') {
886 } else if (cell_data.cell_type === 'html') {
874 new_cell = this.insert_html_cell_below();
887 new_cell = this.insert_html_cell_below();
875 new_cell.fromJSON(cell_data);
888 new_cell.fromJSON(cell_data);
876 } else if (cell_data.cell_type === 'markdown') {
889 } else if (cell_data.cell_type === 'markdown') {
877 new_cell = this.insert_markdown_cell_below();
890 new_cell = this.insert_markdown_cell_below();
878 new_cell.fromJSON(cell_data);
891 new_cell.fromJSON(cell_data);
879 };
892 };
880 };
893 };
881 };
894 };
882 };
895 };
883
896
884
897
885 Notebook.prototype.toJSON = function () {
898 Notebook.prototype.toJSON = function () {
886 var cells = this.cells();
899 var cells = this.cells();
887 var ncells = cells.length;
900 var ncells = cells.length;
888 cell_array = new Array(ncells);
901 cell_array = new Array(ncells);
889 for (var i=0; i<ncells; i++) {
902 for (var i=0; i<ncells; i++) {
890 cell_array[i] = cells[i].toJSON();
903 cell_array[i] = cells[i].toJSON();
891 };
904 };
892 data = {
905 data = {
893 // Only handle 1 worksheet for now.
906 // Only handle 1 worksheet for now.
894 worksheets : [{cells:cell_array}],
907 worksheets : [{cells:cell_array}],
895 metadata : this.metadata
908 metadata : this.metadata
896 }
909 }
897 return data
910 return data
898 };
911 };
899
912
900 Notebook.prototype.save_notebook = function () {
913 Notebook.prototype.save_notebook = function () {
901 if (IPython.save_widget.test_notebook_name()) {
914 if (IPython.save_widget.test_notebook_name()) {
902 var notebook_id = IPython.save_widget.get_notebook_id();
915 var notebook_id = IPython.save_widget.get_notebook_id();
903 var nbname = IPython.save_widget.get_notebook_name();
916 var nbname = IPython.save_widget.get_notebook_name();
904 // We may want to move the name/id/nbformat logic inside toJSON?
917 // We may want to move the name/id/nbformat logic inside toJSON?
905 var data = this.toJSON();
918 var data = this.toJSON();
906 data.metadata.name = nbname;
919 data.metadata.name = nbname;
907 data.nbformat = 2;
920 data.nbformat = 2;
908 // We do the call with settings so we can set cache to false.
921 // We do the call with settings so we can set cache to false.
909 var settings = {
922 var settings = {
910 processData : false,
923 processData : false,
911 cache : false,
924 cache : false,
912 type : "PUT",
925 type : "PUT",
913 data : JSON.stringify(data),
926 data : JSON.stringify(data),
914 headers : {'Content-Type': 'application/json'},
927 headers : {'Content-Type': 'application/json'},
915 success : $.proxy(this.notebook_saved,this)
928 success : $.proxy(this.notebook_saved,this)
916 };
929 };
917 IPython.save_widget.status_saving();
930 IPython.save_widget.status_saving();
918 $.ajax("/notebooks/" + notebook_id, settings);
931 $.ajax("/notebooks/" + notebook_id, settings);
919 };
932 };
920 };
933 };
921
934
922
935
923 Notebook.prototype.notebook_saved = function (data, status, xhr) {
936 Notebook.prototype.notebook_saved = function (data, status, xhr) {
924 this.dirty = false;
937 this.dirty = false;
925 setTimeout($.proxy(IPython.save_widget.status_save,IPython.save_widget),500);
938 setTimeout($.proxy(IPython.save_widget.status_save,IPython.save_widget),500);
926 }
939 }
927
940
928
941
929 Notebook.prototype.load_notebook = function (callback) {
942 Notebook.prototype.load_notebook = function (callback) {
930 var that = this;
943 var that = this;
931 var notebook_id = IPython.save_widget.get_notebook_id();
944 var notebook_id = IPython.save_widget.get_notebook_id();
932 // We do the call with settings so we can set cache to false.
945 // We do the call with settings so we can set cache to false.
933 var settings = {
946 var settings = {
934 processData : false,
947 processData : false,
935 cache : false,
948 cache : false,
936 type : "GET",
949 type : "GET",
937 dataType : "json",
950 dataType : "json",
938 success : function (data, status, xhr) {
951 success : function (data, status, xhr) {
939 that.notebook_loaded(data, status, xhr);
952 that.notebook_loaded(data, status, xhr);
940 if (callback !== undefined) {
953 if (callback !== undefined) {
941 callback();
954 callback();
942 };
955 };
943 }
956 }
944 };
957 };
945 IPython.save_widget.status_loading();
958 IPython.save_widget.status_loading();
946 $.ajax("/notebooks/" + notebook_id, settings);
959 $.ajax("/notebooks/" + notebook_id, settings);
947 }
960 }
948
961
949
962
950 Notebook.prototype.notebook_loaded = function (data, status, xhr) {
963 Notebook.prototype.notebook_loaded = function (data, status, xhr) {
951 this.fromJSON(data);
964 this.fromJSON(data);
952 if (this.ncells() === 0) {
965 if (this.ncells() === 0) {
953 this.insert_code_cell_below();
966 this.insert_code_cell_below();
954 };
967 };
955 IPython.save_widget.status_save();
968 IPython.save_widget.status_save();
956 IPython.save_widget.set_notebook_name(data.metadata.name);
969 IPython.save_widget.set_notebook_name(data.metadata.name);
957 this.start_kernel();
970 this.start_kernel();
958 this.dirty = false;
971 this.dirty = false;
959 // fromJSON always selects the last cell inserted. We need to wait
972 // fromJSON always selects the last cell inserted. We need to wait
960 // until that is done before scrolling to the top.
973 // until that is done before scrolling to the top.
961 setTimeout(function () {
974 setTimeout(function () {
962 IPython.notebook.select(0);
975 IPython.notebook.select(0);
963 IPython.notebook.scroll_to_top();
976 IPython.notebook.scroll_to_top();
964 }, 50);
977 }, 50);
965 };
978 };
966
979
967 IPython.Notebook = Notebook;
980 IPython.Notebook = Notebook;
968
981
969 return IPython;
982 return IPython;
970
983
971 }(IPython));
984 }(IPython));
972
985
@@ -1,39 +1,39
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 // QuickHelp button
9 // QuickHelp button
10 //============================================================================
10 //============================================================================
11
11
12 var IPython = (function (IPython) {
12 var IPython = (function (IPython) {
13
13
14 var QuickHelp = function (selector) {
14 var QuickHelp = function (selector) {
15 this.selector = selector;
15 this.selector = selector;
16 if (this.selector !== undefined) {
16 if (this.selector !== undefined) {
17 this.element = $(selector);
17 this.element = $(selector);
18 this.style();
18 this.style();
19 this.bind_events();
19 this.bind_events();
20 }
20 }
21 };
21 };
22
22
23 QuickHelp.prototype.style = function () {
23 QuickHelp.prototype.style = function () {
24 this.element.find('button#quick_help').button();
24 this.element.find('button#quick_help').button();
25 };
25 };
26
26
27 QuickHelp.prototype.bind_events = function () {
27 QuickHelp.prototype.bind_events = function () {
28 var that = this;
28 var that = this;
29 this.element.find("button#quick_help").click(function () {
29 this.element.find("button#quick_help").click(function () {
30 IPython.notebook.show_keyboard_shortcuts();
30 IPython.notebook.toggle_keyboard_shortcuts();
31 });
31 });
32 };
32 };
33
33
34 // Set module variables
34 // Set module variables
35 IPython.QuickHelp = QuickHelp;
35 IPython.QuickHelp = QuickHelp;
36
36
37 return IPython;
37 return IPython;
38
38
39 }(IPython));
39 }(IPython));
General Comments 0
You need to be logged in to leave comments. Login now