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