##// END OF EJS Templates
Updating JS part of plaintext cell handling.
Brian Granger -
Show More
@@ -1,177 +1,177 b''
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2008-2011 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // MenuBar
10 10 //============================================================================
11 11
12 12 var IPython = (function (IPython) {
13 13
14 14 var MenuBar = function (selector) {
15 15 this.selector = selector;
16 16 if (this.selector !== undefined) {
17 17 this.element = $(selector);
18 18 this.style();
19 19 this.bind_events();
20 20 }
21 21 };
22 22
23 23
24 24 MenuBar.prototype.style = function () {
25 25 $('ul#menus').menubar({
26 26 select : function (event, ui) {
27 27 // The selected cell loses focus when the menu is entered, so we
28 28 // re-select it upon selection.
29 29 var i = IPython.notebook.get_selected_index();
30 30 IPython.notebook.select(i);
31 31 }
32 32 });
33 33 };
34 34
35 35
36 36 MenuBar.prototype.bind_events = function () {
37 37 // File
38 38 this.element.find('#new_notebook').click(function () {
39 39 window.open($('body').data('baseProjectUrl')+'new');
40 40 });
41 41 this.element.find('#open_notebook').click(function () {
42 42 window.open($('body').data('baseProjectUrl'));
43 43 });
44 44 this.element.find('#rename_notebook').click(function () {
45 45 IPython.save_widget.rename_notebook();
46 46 });
47 47 this.element.find('#copy_notebook').click(function () {
48 48 var notebook_id = IPython.save_widget.get_notebook_id();
49 49 var url = $('body').data('baseProjectUrl') + notebook_id + '/copy';
50 50 window.open(url,'_newtab');
51 51 });
52 52 this.element.find('#save_notebook').click(function () {
53 53 IPython.save_widget.save_notebook();
54 54 });
55 55 this.element.find('#download_ipynb').click(function () {
56 56 var notebook_id = IPython.save_widget.get_notebook_id();
57 57 var url = $('body').data('baseProjectUrl') + 'notebooks/' +
58 58 notebook_id + '?format=json';
59 59 window.open(url,'_newtab');
60 60 });
61 61 this.element.find('#download_py').click(function () {
62 62 var notebook_id = IPython.save_widget.get_notebook_id();
63 63 var url = $('body').data('baseProjectUrl') + 'notebooks/' +
64 64 notebook_id + '?format=py';
65 65 window.open(url,'_newtab');
66 66 });
67 67 this.element.find('button#print_notebook').click(function () {
68 68 IPython.print_widget.print_notebook();
69 69 });
70 70 // Edit
71 71 this.element.find('#cut_cell').click(function () {
72 72 IPython.notebook.cut_cell();
73 73 });
74 74 this.element.find('#copy_cell').click(function () {
75 75 IPython.notebook.copy_cell();
76 76 });
77 77 this.element.find('#delete_cell').click(function () {
78 78 IPython.notebook.delete_cell();
79 79 });
80 80 this.element.find('#split_cell').click(function () {
81 81 IPython.notebook.split_cell();
82 82 });
83 83 this.element.find('#merge_cell_above').click(function () {
84 84 IPython.notebook.merge_cell_above();
85 85 });
86 86 this.element.find('#merge_cell_below').click(function () {
87 87 IPython.notebook.merge_cell_below();
88 88 });
89 89 this.element.find('#move_cell_up').click(function () {
90 90 IPython.notebook.move_cell_up();
91 91 });
92 92 this.element.find('#move_cell_down').click(function () {
93 93 IPython.notebook.move_cell_down();
94 94 });
95 95 this.element.find('#select_previous').click(function () {
96 96 IPython.notebook.select_prev();
97 97 });
98 98 this.element.find('#select_next').click(function () {
99 99 IPython.notebook.select_next();
100 100 });
101 101 // View
102 102 this.element.find('#toggle_header').click(function () {
103 103 $('div#header').toggle();
104 104 IPython.layout_manager.do_resize();
105 105 });
106 106 this.element.find('#toggle_toolbar').click(function () {
107 107 IPython.toolbar.toggle();
108 108 });
109 109 // Insert
110 110 this.element.find('#insert_cell_above').click(function () {
111 111 IPython.notebook.insert_cell_above('code');
112 112 });
113 113 this.element.find('#insert_cell_below').click(function () {
114 114 IPython.notebook.insert_cell_below('code');
115 115 });
116 116 // Cell
117 117 this.element.find('#run_cell').click(function () {
118 118 IPython.notebook.execute_selected_cell();
119 119 });
120 120 this.element.find('#run_cell_in_place').click(function () {
121 121 IPython.notebook.execute_selected_cell({terminal:true});
122 122 });
123 123 this.element.find('#run_all_cells').click(function () {
124 124 IPython.notebook.execute_all_cells();
125 125 });
126 126 this.element.find('#to_code').click(function () {
127 127 IPython.notebook.to_code();
128 128 });
129 129 this.element.find('#to_markdown').click(function () {
130 130 IPython.notebook.to_markdown();
131 131 });
132 this.element.find('#to_rst').click(function () {
133 IPython.notebook.to_rst();
132 this.element.find('#to_plaintext').click(function () {
133 IPython.notebook.to_plaintext();
134 134 });
135 135 this.element.find('#to_heading1').click(function () {
136 136 IPython.notebook.to_heading(undefined, 1);
137 137 });
138 138 this.element.find('#to_heading2').click(function () {
139 139 IPython.notebook.to_heading(undefined, 2);
140 140 });
141 141 this.element.find('#to_heading3').click(function () {
142 142 IPython.notebook.to_heading(undefined, 3);
143 143 });
144 144 this.element.find('#to_heading4').click(function () {
145 145 IPython.notebook.to_heading(undefined, 4);
146 146 });
147 147 this.element.find('#to_heading5').click(function () {
148 148 IPython.notebook.to_heading(undefined, 5);
149 149 });
150 150 this.element.find('#to_heading6').click(function () {
151 151 IPython.notebook.to_heading(undefined, 6);
152 152 });
153 153 this.element.find('#toggle_output').click(function () {
154 154 IPython.notebook.toggle_output();
155 155 });
156 156 this.element.find('#clear_all_output').click(function () {
157 157 IPython.notebook.clear_all_output();
158 158 });
159 159 // Kernel
160 160 this.element.find('#int_kernel').click(function () {
161 161 IPython.notebook.kernel.interrupt();
162 162 });
163 163 this.element.find('#restart_kernel').click(function () {
164 164 IPython.notebook.restart_kernel();
165 165 });
166 166 // Help
167 167 this.element.find('#keyboard_shortcuts').click(function () {
168 168 IPython.quick_help.show_keyboard_shortcuts();
169 169 });
170 170 };
171 171
172 172
173 173 IPython.MenuBar = MenuBar;
174 174
175 175 return IPython;
176 176
177 177 }(IPython));
@@ -1,1260 +1,1260 b''
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2008-2011 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // Notebook
10 10 //============================================================================
11 11
12 12 var IPython = (function (IPython) {
13 13
14 14 var utils = IPython.utils;
15 15
16 16 var Notebook = function (selector) {
17 17 this.read_only = IPython.read_only;
18 18 this.element = $(selector);
19 19 this.element.scroll();
20 20 this.element.data("notebook", this);
21 21 this.next_prompt_number = 1;
22 22 this.kernel = null;
23 23 this.clipboard = null;
24 24 this.paste_enabled = false;
25 25 this.dirty = false;
26 26 this.msg_cell_map = {};
27 27 this.metadata = {};
28 28 this.control_key_active = false;
29 29 this.style();
30 30 this.create_elements();
31 31 this.bind_events();
32 32 this.set_tooltipontab(true);
33 33 this.set_smartcompleter(true);
34 34 this.set_timebeforetooltip(1200);
35 35 };
36 36
37 37
38 38 Notebook.prototype.style = function () {
39 39 $('div#notebook').addClass('border-box-sizing');
40 40 };
41 41
42 42
43 43 Notebook.prototype.create_elements = function () {
44 44 // We add this end_space div to the end of the notebook div to:
45 45 // i) provide a margin between the last cell and the end of the notebook
46 46 // ii) to prevent the div from scrolling up when the last cell is being
47 47 // edited, but is too low on the page, which browsers will do automatically.
48 48 var that = this;
49 49 var end_space = $('<div/>').addClass('end_space').height("30%");
50 50 end_space.dblclick(function (e) {
51 51 if (that.read_only) return;
52 52 var ncells = that.ncells();
53 53 that.insert_cell_below('code',ncells-1);
54 54 });
55 55 this.element.append(end_space);
56 56 $('div#notebook').addClass('border-box-sizing');
57 57 };
58 58
59 59
60 60 Notebook.prototype.bind_events = function () {
61 61 var that = this;
62 62 $(document).keydown(function (event) {
63 63 // console.log(event);
64 64 if (that.read_only) return true;
65 65
66 66 // Save (CTRL+S) or (AppleKey+S)
67 67 //metaKey = applekey on mac
68 68 if ((event.ctrlKey || event.metaKey) && event.keyCode==83) {
69 69 IPython.save_widget.save_notebook();
70 70 event.preventDefault();
71 71 return false;
72 72 } else if (event.which === 27) {
73 73 // Intercept escape at highest level to avoid closing
74 74 // websocket connection with firefox
75 75 event.preventDefault();
76 76 }
77 77 if (event.which === 38 && !event.shiftKey) {
78 78 var cell = that.get_selected_cell();
79 79 if (cell.at_top()) {
80 80 event.preventDefault();
81 81 that.select_prev();
82 82 };
83 83 } else if (event.which === 40 && !event.shiftKey) {
84 84 var cell = that.get_selected_cell();
85 85 if (cell.at_bottom()) {
86 86 event.preventDefault();
87 87 that.select_next();
88 88 };
89 89 } else if (event.which === 13 && event.shiftKey) {
90 90 that.execute_selected_cell();
91 91 return false;
92 92 } else if (event.which === 13 && event.ctrlKey) {
93 93 that.execute_selected_cell({terminal:true});
94 94 return false;
95 95 } else if (event.which === 77 && event.ctrlKey) {
96 96 that.control_key_active = true;
97 97 return false;
98 98 } else if (event.which === 88 && that.control_key_active) {
99 99 // Cut selected cell = x
100 100 that.cut_cell();
101 101 that.control_key_active = false;
102 102 return false;
103 103 } else if (event.which === 67 && that.control_key_active) {
104 104 // Copy selected cell = c
105 105 that.copy_cell();
106 106 that.control_key_active = false;
107 107 return false;
108 108 } else if (event.which === 86 && that.control_key_active) {
109 109 // Paste selected cell = v
110 110 that.paste_cell();
111 111 that.control_key_active = false;
112 112 return false;
113 113 } else if (event.which === 68 && that.control_key_active) {
114 114 // Delete selected cell = d
115 115 that.delete_cell();
116 116 that.control_key_active = false;
117 117 return false;
118 118 } else if (event.which === 65 && that.control_key_active) {
119 119 // Insert code cell above selected = a
120 120 that.insert_cell_above('code');
121 121 that.control_key_active = false;
122 122 return false;
123 123 } else if (event.which === 66 && that.control_key_active) {
124 124 // Insert code cell below selected = b
125 125 that.insert_cell_below('code');
126 126 that.control_key_active = false;
127 127 return false;
128 128 } else if (event.which === 89 && that.control_key_active) {
129 129 // To code = y
130 130 that.to_code();
131 131 that.control_key_active = false;
132 132 return false;
133 133 } else if (event.which === 77 && that.control_key_active) {
134 134 // To markdown = m
135 135 that.to_markdown();
136 136 that.control_key_active = false;
137 137 return false;
138 } else if (event.which === 82 && that.control_key_active) {
139 // To RST = r
140 that.to_rst();
138 } else if (event.which === 84 && that.control_key_active) {
139 // To Plaintext = r
140 that.to_plaintext();
141 141 that.control_key_active = false;
142 142 return false;
143 143 } else if (event.which === 49 && that.control_key_active) {
144 144 // To Heading 1 = 1
145 145 that.to_heading(undefined, 1);
146 146 that.control_key_active = false;
147 147 return false;
148 148 } else if (event.which === 50 && that.control_key_active) {
149 149 // To Heading 2 = 2
150 150 that.to_heading(undefined, 2);
151 151 that.control_key_active = false;
152 152 return false;
153 153 } else if (event.which === 51 && that.control_key_active) {
154 154 // To Heading 3 = 3
155 155 that.to_heading(undefined, 3);
156 156 that.control_key_active = false;
157 157 return false;
158 158 } else if (event.which === 52 && that.control_key_active) {
159 159 // To Heading 4 = 4
160 160 that.to_heading(undefined, 4);
161 161 that.control_key_active = false;
162 162 return false;
163 163 } else if (event.which === 53 && that.control_key_active) {
164 164 // To Heading 5 = 5
165 165 that.to_heading(undefined, 5);
166 166 that.control_key_active = false;
167 167 return false;
168 168 } else if (event.which === 54 && that.control_key_active) {
169 169 // To Heading 6 = 6
170 170 that.to_heading(undefined, 6);
171 171 that.control_key_active = false;
172 172 return false;
173 } else if (event.which === 84 && that.control_key_active) {
174 // Toggle output = t
173 } else if (event.which === 79 && that.control_key_active) {
174 // Toggle output = o
175 175 that.toggle_output();
176 176 that.control_key_active = false;
177 177 return false;
178 178 } else if (event.which === 83 && that.control_key_active) {
179 179 // Save notebook = s
180 180 IPython.save_widget.save_notebook();
181 181 that.control_key_active = false;
182 182 return false;
183 183 } else if (event.which === 74 && that.control_key_active) {
184 184 // Move cell down = j
185 185 that.move_cell_down();
186 186 that.control_key_active = false;
187 187 return false;
188 188 } else if (event.which === 75 && that.control_key_active) {
189 189 // Move cell up = k
190 190 that.move_cell_up();
191 191 that.control_key_active = false;
192 192 return false;
193 193 } else if (event.which === 80 && that.control_key_active) {
194 194 // Select previous = p
195 195 that.select_prev();
196 196 that.control_key_active = false;
197 197 return false;
198 198 } else if (event.which === 78 && that.control_key_active) {
199 199 // Select next = n
200 200 that.select_next();
201 201 that.control_key_active = false;
202 202 return false;
203 203 } else if (event.which === 76 && that.control_key_active) {
204 204 // Toggle line numbers = l
205 205 that.cell_toggle_line_numbers();
206 206 that.control_key_active = false;
207 207 return false;
208 208 } else if (event.which === 73 && that.control_key_active) {
209 209 // Interrupt kernel = i
210 210 IPython.notebook.kernel.interrupt();
211 211 that.control_key_active = false;
212 212 return false;
213 213 } else if (event.which === 190 && that.control_key_active) {
214 214 // Restart kernel = . # matches qt console
215 215 IPython.notebook.restart_kernel();
216 216 that.control_key_active = false;
217 217 return false;
218 218 } else if (event.which === 72 && that.control_key_active) {
219 219 // Show keyboard shortcuts = h
220 220 IPython.quick_help.show_keyboard_shortcuts();
221 221 that.control_key_active = false;
222 222 return false;
223 223 } else if (that.control_key_active) {
224 224 that.control_key_active = false;
225 225 return true;
226 226 };
227 227 return true;
228 228 });
229 229
230 230 this.element.bind('collapse_pager', function () {
231 231 var app_height = $('div#main_app').height(); // content height
232 232 var splitter_height = $('div#pager_splitter').outerHeight(true);
233 233 var new_height = app_height - splitter_height;
234 234 that.element.animate({height : new_height + 'px'}, 'fast');
235 235 });
236 236
237 237 this.element.bind('expand_pager', function () {
238 238 var app_height = $('div#main_app').height(); // content height
239 239 var splitter_height = $('div#pager_splitter').outerHeight(true);
240 240 var pager_height = $('div#pager').outerHeight(true);
241 241 var new_height = app_height - pager_height - splitter_height;
242 242 that.element.animate({height : new_height + 'px'}, 'fast');
243 243 });
244 244
245 245 $(window).bind('beforeunload', function () {
246 246 // TODO: Make killing the kernel configurable.
247 247 var kill_kernel = false;
248 248 if (kill_kernel) {
249 249 that.kernel.kill();
250 250 }
251 251 if (that.dirty && ! that.read_only) {
252 252 return "You have unsaved changes that will be lost if you leave this page.";
253 253 };
254 254 // Null is the *only* return value that will make the browser not
255 255 // pop up the "don't leave" dialog.
256 256 return null;
257 257 });
258 258 };
259 259
260 260
261 261 Notebook.prototype.scroll_to_bottom = function () {
262 262 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
263 263 };
264 264
265 265
266 266 Notebook.prototype.scroll_to_top = function () {
267 267 this.element.animate({scrollTop:0}, 0);
268 268 };
269 269
270 270
271 271 // Cell indexing, retrieval, etc.
272 272
273 273 Notebook.prototype.get_cell_elements = function () {
274 274 return this.element.children("div.cell");
275 275 };
276 276
277 277
278 278 Notebook.prototype.get_cell_element = function (index) {
279 279 var result = null;
280 280 var e = this.get_cell_elements().eq(index);
281 281 if (e.length !== 0) {
282 282 result = e;
283 283 }
284 284 return result;
285 285 };
286 286
287 287
288 288 Notebook.prototype.ncells = function (cell) {
289 289 return this.get_cell_elements().length;
290 290 };
291 291
292 292
293 293 // TODO: we are often calling cells as cells()[i], which we should optimize
294 294 // to cells(i) or a new method.
295 295 Notebook.prototype.get_cells = function () {
296 296 return this.get_cell_elements().toArray().map(function (e) {
297 297 return $(e).data("cell");
298 298 });
299 299 };
300 300
301 301
302 302 Notebook.prototype.get_cell = function (index) {
303 303 var result = null;
304 304 var ce = this.get_cell_element(index);
305 305 if (ce !== null) {
306 306 result = ce.data('cell');
307 307 }
308 308 return result;
309 309 }
310 310
311 311
312 312 Notebook.prototype.get_next_cell = function (cell) {
313 313 var result = null;
314 314 var index = this.find_cell_index(cell);
315 315 if (index !== null && index < this.ncells()) {
316 316 result = this.get_cell(index+1);
317 317 }
318 318 return result;
319 319 }
320 320
321 321
322 322 Notebook.prototype.get_prev_cell = function (cell) {
323 323 var result = null;
324 324 var index = this.find_cell_index(cell);
325 325 if (index !== null && index > 1) {
326 326 result = this.get_cell(index-1);
327 327 }
328 328 return result;
329 329 }
330 330
331 331 Notebook.prototype.find_cell_index = function (cell) {
332 332 var result = null;
333 333 this.get_cell_elements().filter(function (index) {
334 334 if ($(this).data("cell") === cell) {
335 335 result = index;
336 336 };
337 337 });
338 338 return result;
339 339 };
340 340
341 341
342 342 Notebook.prototype.index_or_selected = function (index) {
343 343 var i;
344 344 if (index === undefined || index === null) {
345 345 i = this.get_selected_index();
346 346 if (i === null) {
347 347 i = 0;
348 348 }
349 349 } else {
350 350 i = index;
351 351 }
352 352 return i;
353 353 };
354 354
355 355
356 356 Notebook.prototype.get_selected_cell = function () {
357 357 var index = this.get_selected_index();
358 358 return this.get_cell(index);
359 359 };
360 360
361 361
362 362 Notebook.prototype.is_valid_cell_index = function (index) {
363 363 if (index !== null && index >= 0 && index < this.ncells()) {
364 364 return true;
365 365 } else {
366 366 return false;
367 367 };
368 368 }
369 369
370 370 Notebook.prototype.get_selected_index = function () {
371 371 var result = null;
372 372 this.get_cell_elements().filter(function (index) {
373 373 if ($(this).data("cell").selected === true) {
374 374 result = index;
375 375 };
376 376 });
377 377 return result;
378 378 };
379 379
380 380
381 381 Notebook.prototype.cell_for_msg = function (msg_id) {
382 382 var cell_id = this.msg_cell_map[msg_id];
383 383 var result = null;
384 384 this.get_cell_elements().filter(function (index) {
385 385 cell = $(this).data("cell");
386 386 if (cell.cell_id === cell_id) {
387 387 result = cell;
388 388 };
389 389 });
390 390 return result;
391 391 };
392 392
393 393
394 394 // Cell selection.
395 395
396 396 Notebook.prototype.select = function (index) {
397 397 if (index !== undefined && index >= 0 && index < this.ncells()) {
398 398 sindex = this.get_selected_index()
399 399 if (sindex !== null && index !== sindex) {
400 400 this.get_cell(sindex).unselect();
401 401 };
402 402 var cell = this.get_cell(index)
403 403 cell.select();
404 404 IPython.toolbar.set_cell_type(cell.cell_type);
405 405 };
406 406 return this;
407 407 };
408 408
409 409
410 410 Notebook.prototype.select_next = function () {
411 411 var index = this.get_selected_index();
412 412 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
413 413 this.select(index+1);
414 414 };
415 415 return this;
416 416 };
417 417
418 418
419 419 Notebook.prototype.select_prev = function () {
420 420 var index = this.get_selected_index();
421 421 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
422 422 this.select(index-1);
423 423 };
424 424 return this;
425 425 };
426 426
427 427
428 428 // Cell movement
429 429
430 430 Notebook.prototype.move_cell_up = function (index) {
431 431 var i = this.index_or_selected();
432 432 if (i !== null && i < this.ncells() && i > 0) {
433 433 var pivot = this.get_cell_element(i-1);
434 434 var tomove = this.get_cell_element(i);
435 435 if (pivot !== null && tomove !== null) {
436 436 tomove.detach();
437 437 pivot.before(tomove);
438 438 this.select(i-1);
439 439 };
440 440 };
441 441 this.dirty = true;
442 442 return this;
443 443 };
444 444
445 445
446 446 Notebook.prototype.move_cell_down = function (index) {
447 447 var i = this.index_or_selected();
448 448 if (i !== null && i < (this.ncells()-1) && i >= 0) {
449 449 var pivot = this.get_cell_element(i+1);
450 450 var tomove = this.get_cell_element(i);
451 451 if (pivot !== null && tomove !== null) {
452 452 tomove.detach();
453 453 pivot.after(tomove);
454 454 this.select(i+1);
455 455 };
456 456 };
457 457 this.dirty = true;
458 458 return this;
459 459 };
460 460
461 461
462 462 Notebook.prototype.sort_cells = function () {
463 463 // This is not working right now. Calling this will actually crash
464 464 // the browser. I think there is an infinite loop in here...
465 465 var ncells = this.ncells();
466 466 var sindex = this.get_selected_index();
467 467 var swapped;
468 468 do {
469 469 swapped = false;
470 470 for (var i=1; i<ncells; i++) {
471 471 current = this.get_cell(i);
472 472 previous = this.get_cell(i-1);
473 473 if (previous.input_prompt_number > current.input_prompt_number) {
474 474 this.move_cell_up(i);
475 475 swapped = true;
476 476 };
477 477 };
478 478 } while (swapped);
479 479 this.select(sindex);
480 480 return this;
481 481 };
482 482
483 483 // Insertion, deletion.
484 484
485 485 Notebook.prototype.delete_cell = function (index) {
486 486 var i = this.index_or_selected(index);
487 487 if (this.is_valid_cell_index(i)) {
488 488 var ce = this.get_cell_element(i);
489 489 ce.remove();
490 490 if (i === (this.ncells())) {
491 491 this.select(i-1);
492 492 } else {
493 493 this.select(i);
494 494 };
495 495 this.dirty = true;
496 496 };
497 497 return this;
498 498 };
499 499
500 500
501 501 Notebook.prototype.insert_cell_below = function (type, index) {
502 502 // type = ('code','html','markdown')
503 503 // index = cell index or undefined to insert below selected
504 504 index = this.index_or_selected(index);
505 505 var cell = null;
506 506 if (this.ncells() === 0 || this.is_valid_cell_index(index)) {
507 507 if (type === 'code') {
508 508 cell = new IPython.CodeCell(this);
509 509 cell.set_input_prompt();
510 510 } else if (type === 'markdown') {
511 511 cell = new IPython.MarkdownCell(this);
512 512 } else if (type === 'html') {
513 513 cell = new IPython.HTMLCell(this);
514 } else if (type === 'rst') {
515 cell = new IPython.RSTCell(this);
514 } else if (type === 'plaintext') {
515 cell = new IPython.PlaintextCell(this);
516 516 } else if (type === 'heading') {
517 517 cell = new IPython.HeadingCell(this);
518 518 };
519 519 if (cell !== null) {
520 520 if (this.ncells() === 0) {
521 521 this.element.find('div.end_space').before(cell.element);
522 522 } else if (this.is_valid_cell_index(index)) {
523 523 this.get_cell_element(index).after(cell.element);
524 524 };
525 525 cell.render();
526 526 this.select(this.find_cell_index(cell));
527 527 this.dirty = true;
528 528 return cell;
529 529 };
530 530 };
531 531 return cell;
532 532 };
533 533
534 534
535 535 Notebook.prototype.insert_cell_above = function (type, index) {
536 536 // type = ('code','html','markdown')
537 537 // index = cell index or undefined to insert above selected
538 538 index = this.index_or_selected(index);
539 539 var cell = null;
540 540 if (this.ncells() === 0 || this.is_valid_cell_index(index)) {
541 541 if (type === 'code') {
542 542 cell = new IPython.CodeCell(this);
543 543 cell.set_input_prompt();
544 544 } else if (type === 'markdown') {
545 545 cell = new IPython.MarkdownCell(this);
546 546 } else if (type === 'html') {
547 547 cell = new IPython.HTMLCell(this);
548 } else if (type === 'rst') {
549 cell = new IPython.RSTCell(this);
548 } else if (type === 'plaintext') {
549 cell = new IPython.PlaintextCell(this);
550 550 } else if (type === 'heading') {
551 551 cell = new IPython.HeadingCell(this);
552 552 };
553 553 if (cell !== null) {
554 554 if (this.ncells() === 0) {
555 555 this.element.find('div.end_space').before(cell.element);
556 556 } else if (this.is_valid_cell_index(index)) {
557 557 this.get_cell_element(index).before(cell.element);
558 558 };
559 559 cell.render();
560 560 this.select(this.find_cell_index(cell));
561 561 this.dirty = true;
562 562 return cell;
563 563 };
564 564 };
565 565 return cell;
566 566 };
567 567
568 568
569 569 Notebook.prototype.to_code = function (index) {
570 570 var i = this.index_or_selected(index);
571 571 if (this.is_valid_cell_index(i)) {
572 572 var source_element = this.get_cell_element(i);
573 573 var source_cell = source_element.data("cell");
574 574 if (!(source_cell instanceof IPython.CodeCell)) {
575 575 target_cell = this.insert_cell_below('code',i);
576 576 var text = source_cell.get_text();
577 577 if (text === source_cell.placeholder) {
578 578 text = '';
579 579 }
580 580 target_cell.set_text(text);
581 581 source_element.remove();
582 582 this.dirty = true;
583 583 };
584 584 };
585 585 };
586 586
587 587
588 588 Notebook.prototype.to_markdown = function (index) {
589 589 var i = this.index_or_selected(index);
590 590 if (this.is_valid_cell_index(i)) {
591 591 var source_element = this.get_cell_element(i);
592 592 var source_cell = source_element.data("cell");
593 593 if (!(source_cell instanceof IPython.MarkdownCell)) {
594 594 target_cell = this.insert_cell_below('markdown',i);
595 595 var text = source_cell.get_text();
596 596 if (text === source_cell.placeholder) {
597 597 text = '';
598 598 };
599 599 // The edit must come before the set_text.
600 600 target_cell.edit();
601 601 target_cell.set_text(text);
602 602 source_element.remove();
603 603 this.dirty = true;
604 604 };
605 605 };
606 606 };
607 607
608 608
609 609 Notebook.prototype.to_html = function (index) {
610 610 var i = this.index_or_selected(index);
611 611 if (this.is_valid_cell_index(i)) {
612 612 var source_element = this.get_cell_element(i);
613 613 var source_cell = source_element.data("cell");
614 614 var target_cell = null;
615 615 if (!(source_cell instanceof IPython.HTMLCell)) {
616 616 target_cell = this.insert_cell_below('html',i);
617 617 var text = source_cell.get_text();
618 618 if (text === source_cell.placeholder) {
619 619 text = '';
620 620 };
621 621 // The edit must come before the set_text.
622 622 target_cell.edit();
623 623 target_cell.set_text(text);
624 624 source_element.remove();
625 625 this.dirty = true;
626 626 };
627 627 };
628 628 };
629 629
630 630
631 Notebook.prototype.to_rst = function (index) {
631 Notebook.prototype.to_plaintext = function (index) {
632 632 var i = this.index_or_selected(index);
633 633 if (this.is_valid_cell_index(i)) {
634 634 var source_element = this.get_cell_element(i);
635 635 var source_cell = source_element.data("cell");
636 636 var target_cell = null;
637 if (!(source_cell instanceof IPython.RSTCell)) {
638 target_cell = this.insert_cell_below('rst',i);
637 if (!(source_cell instanceof IPython.PlaintextCell)) {
638 target_cell = this.insert_cell_below('plaintext',i);
639 639 var text = source_cell.get_text();
640 640 if (text === source_cell.placeholder) {
641 641 text = '';
642 642 };
643 643 // The edit must come before the set_text.
644 644 target_cell.edit();
645 645 target_cell.set_text(text);
646 646 source_element.remove();
647 647 this.dirty = true;
648 648 };
649 649 };
650 650 };
651 651
652 652
653 653 Notebook.prototype.to_heading = function (index, level) {
654 654 level = level || 1;
655 655 var i = this.index_or_selected(index);
656 656 if (this.is_valid_cell_index(i)) {
657 657 var source_element = this.get_cell_element(i);
658 658 var source_cell = source_element.data("cell");
659 659 var target_cell = null;
660 660 if (source_cell instanceof IPython.HeadingCell) {
661 661 source_cell.set_level(level);
662 662 } else {
663 663 target_cell = this.insert_cell_below('heading',i);
664 664 var text = source_cell.get_text();
665 665 if (text === source_cell.placeholder) {
666 666 text = '';
667 667 };
668 668 // The edit must come before the set_text.
669 669 target_cell.set_level(level);
670 670 target_cell.edit();
671 671 target_cell.set_text(text);
672 672 source_element.remove();
673 673 this.dirty = true;
674 674 };
675 675 };
676 676 };
677 677
678 678
679 679 // Cut/Copy/Paste
680 680
681 681 Notebook.prototype.enable_paste = function () {
682 682 var that = this;
683 683 if (!this.paste_enabled) {
684 684 $('#paste_cell').removeClass('ui-state-disabled')
685 685 .on('click', function () {that.paste_cell();});
686 686 $('#paste_cell_above').removeClass('ui-state-disabled')
687 687 .on('click', function () {that.paste_cell_above();});
688 688 $('#paste_cell_below').removeClass('ui-state-disabled')
689 689 .on('click', function () {that.paste_cell_below();});
690 690 this.paste_enabled = true;
691 691 };
692 692 };
693 693
694 694
695 695 Notebook.prototype.disable_paste = function () {
696 696 if (this.paste_enabled) {
697 697 $('#paste_cell').addClass('ui-state-disabled').off('click');
698 698 $('#paste_cell_above').addClass('ui-state-disabled').off('click');
699 699 $('#paste_cell_below').addClass('ui-state-disabled').off('click');
700 700 this.paste_enabled = false;
701 701 };
702 702 };
703 703
704 704
705 705 Notebook.prototype.cut_cell = function () {
706 706 this.copy_cell();
707 707 this.delete_cell();
708 708 }
709 709
710 710 Notebook.prototype.copy_cell = function () {
711 711 var cell = this.get_selected_cell();
712 712 this.clipboard = cell.toJSON();
713 713 this.enable_paste();
714 714 };
715 715
716 716
717 717 Notebook.prototype.paste_cell = function () {
718 718 if (this.clipboard !== null && this.paste_enabled) {
719 719 var cell_data = this.clipboard;
720 720 var new_cell = this.insert_cell_above(cell_data.cell_type);
721 721 new_cell.fromJSON(cell_data);
722 722 old_cell = this.get_next_cell(new_cell);
723 723 this.delete_cell(this.find_cell_index(old_cell));
724 724 this.select(this.find_cell_index(new_cell));
725 725 };
726 726 };
727 727
728 728
729 729 Notebook.prototype.paste_cell_above = function () {
730 730 if (this.clipboard !== null && this.paste_enabled) {
731 731 var cell_data = this.clipboard;
732 732 var new_cell = this.insert_cell_above(cell_data.cell_type);
733 733 new_cell.fromJSON(cell_data);
734 734 };
735 735 };
736 736
737 737
738 738 Notebook.prototype.paste_cell_below = function () {
739 739 if (this.clipboard !== null && this.paste_enabled) {
740 740 var cell_data = this.clipboard;
741 741 var new_cell = this.insert_cell_below(cell_data.cell_type);
742 742 new_cell.fromJSON(cell_data);
743 743 };
744 744 };
745 745
746 746
747 747 // Split/merge
748 748
749 749 Notebook.prototype.split_cell = function () {
750 750 // Todo: implement spliting for other cell types.
751 751 var cell = this.get_selected_cell();
752 752 if (cell.is_splittable()) {
753 753 texta = cell.get_pre_cursor();
754 754 textb = cell.get_post_cursor();
755 755 if (cell instanceof IPython.CodeCell) {
756 756 cell.set_text(texta);
757 757 var new_cell = this.insert_cell_below('code');
758 758 new_cell.set_text(textb);
759 759 } else if (cell instanceof IPython.MarkdownCell) {
760 760 cell.set_text(texta);
761 761 cell.render();
762 762 var new_cell = this.insert_cell_below('markdown');
763 763 new_cell.edit(); // editor must be visible to call set_text
764 764 new_cell.set_text(textb);
765 765 new_cell.render();
766 766 } else if (cell instanceof IPython.HTMLCell) {
767 767 cell.set_text(texta);
768 768 cell.render();
769 769 var new_cell = this.insert_cell_below('html');
770 770 new_cell.edit(); // editor must be visible to call set_text
771 771 new_cell.set_text(textb);
772 772 new_cell.render();
773 773 };
774 774 };
775 775 };
776 776
777 777
778 778 Notebook.prototype.merge_cell_above = function () {
779 779 var index = this.get_selected_index();
780 780 var cell = this.get_cell(index);
781 781 if (index > 0) {
782 782 upper_cell = this.get_cell(index-1);
783 783 upper_text = upper_cell.get_text();
784 784 text = cell.get_text();
785 785 if (cell instanceof IPython.CodeCell) {
786 786 cell.set_text(upper_text+'\n'+text);
787 787 } else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) {
788 788 cell.edit();
789 789 cell.set_text(upper_text+'\n'+text);
790 790 cell.render();
791 791 };
792 792 this.delete_cell(index-1);
793 793 this.select(this.find_cell_index(cell));
794 794 };
795 795 };
796 796
797 797
798 798 Notebook.prototype.merge_cell_below = function () {
799 799 var index = this.get_selected_index();
800 800 var cell = this.get_cell(index);
801 801 if (index < this.ncells()-1) {
802 802 lower_cell = this.get_cell(index+1);
803 803 lower_text = lower_cell.get_text();
804 804 text = cell.get_text();
805 805 if (cell instanceof IPython.CodeCell) {
806 806 cell.set_text(text+'\n'+lower_text);
807 807 } else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) {
808 808 cell.edit();
809 809 cell.set_text(text+'\n'+lower_text);
810 810 cell.render();
811 811 };
812 812 this.delete_cell(index+1);
813 813 this.select(this.find_cell_index(cell));
814 814 };
815 815 };
816 816
817 817
818 818 // Cell collapsing and output clearing
819 819
820 820 Notebook.prototype.collapse = function (index) {
821 821 var i = this.index_or_selected(index);
822 822 this.get_cell(i).collapse();
823 823 this.dirty = true;
824 824 };
825 825
826 826
827 827 Notebook.prototype.expand = function (index) {
828 828 var i = this.index_or_selected(index);
829 829 this.get_cell(i).expand();
830 830 this.dirty = true;
831 831 };
832 832
833 833
834 834 Notebook.prototype.toggle_output = function (index) {
835 835 var i = this.index_or_selected(index);
836 836 this.get_cell(i).toggle_output();
837 837 this.dirty = true;
838 838 };
839 839
840 840
841 841 Notebook.prototype.set_timebeforetooltip = function (time) {
842 842 this.time_before_tooltip = time;
843 843 };
844 844
845 845
846 846 Notebook.prototype.set_tooltipontab = function (state) {
847 847 this.tooltip_on_tab = state;
848 848 };
849 849
850 850
851 851 Notebook.prototype.set_smartcompleter = function (state) {
852 852 this.smart_completer = state;
853 853 };
854 854
855 855
856 856 Notebook.prototype.clear_all_output = function () {
857 857 var ncells = this.ncells();
858 858 var cells = this.get_cells();
859 859 for (var i=0; i<ncells; i++) {
860 860 if (cells[i] instanceof IPython.CodeCell) {
861 861 cells[i].clear_output(true,true,true);
862 862 }
863 863 };
864 864 this.dirty = true;
865 865 };
866 866
867 867
868 868 // Other cell functions: line numbers, ...
869 869
870 870 Notebook.prototype.cell_toggle_line_numbers = function() {
871 871 this.get_selected_cell().toggle_line_numbers();
872 872 };
873 873
874 874 // Kernel related things
875 875
876 876 Notebook.prototype.start_kernel = function () {
877 877 this.kernel = new IPython.Kernel();
878 878 var notebook_id = IPython.save_widget.get_notebook_id();
879 879 this.kernel.start(notebook_id, $.proxy(this.kernel_started, this));
880 880 };
881 881
882 882
883 883 Notebook.prototype.restart_kernel = function () {
884 884 var that = this;
885 885 var notebook_id = IPython.save_widget.get_notebook_id();
886 886
887 887 var dialog = $('<div/>');
888 888 dialog.html('Do you want to restart the current kernel? You will lose all variables defined in it.');
889 889 $(document).append(dialog);
890 890 dialog.dialog({
891 891 resizable: false,
892 892 modal: true,
893 893 title: "Restart kernel or continue running?",
894 894 closeText: '',
895 895 buttons : {
896 896 "Restart": function () {
897 897 that.kernel.restart($.proxy(that.kernel_started, that));
898 898 $(this).dialog('close');
899 899 },
900 900 "Continue running": function () {
901 901 $(this).dialog('close');
902 902 }
903 903 }
904 904 });
905 905 };
906 906
907 907
908 908 Notebook.prototype.kernel_started = function () {
909 909 console.log("Kernel started: ", this.kernel.kernel_id);
910 910 this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
911 911 this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
912 912 };
913 913
914 914
915 915 Notebook.prototype.handle_shell_reply = function (e) {
916 916 reply = $.parseJSON(e.data);
917 917 var header = reply.header;
918 918 var content = reply.content;
919 919 var msg_type = header.msg_type;
920 920 // console.log(reply);
921 921 var cell = this.cell_for_msg(reply.parent_header.msg_id);
922 922 if (msg_type === "execute_reply") {
923 923 cell.set_input_prompt(content.execution_count);
924 924 cell.element.removeClass("running");
925 925 this.dirty = true;
926 926 } else if (msg_type === "complete_reply") {
927 927 cell.finish_completing(content.matched_text, content.matches);
928 928 } else if (msg_type === "object_info_reply"){
929 929 //console.log('back from object_info_request : ')
930 930 rep = reply.content;
931 931 if(rep.found)
932 932 {
933 933 cell.finish_tooltip(rep);
934 934 }
935 935 } else {
936 936 //console.log("unknown reply:"+msg_type);
937 937 }
938 938 // when having a rely from object_info_reply,
939 939 // no payload so no nned to handle it
940 940 if(typeof(content.payload)!='undefined') {
941 941 var payload = content.payload || [];
942 942 this.handle_payload(cell, payload);
943 943 }
944 944 };
945 945
946 946
947 947 Notebook.prototype.handle_payload = function (cell, payload) {
948 948 var l = payload.length;
949 949 for (var i=0; i<l; i++) {
950 950 if (payload[i].source === 'IPython.zmq.page.page') {
951 951 if (payload[i].text.trim() !== '') {
952 952 IPython.pager.clear();
953 953 IPython.pager.expand();
954 954 IPython.pager.append_text(payload[i].text);
955 955 }
956 956 } else if (payload[i].source === 'IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input') {
957 957 var index = this.find_cell_index(cell);
958 958 var new_cell = this.insert_cell_below('code',index);
959 959 new_cell.set_text(payload[i].text);
960 960 this.dirty = true;
961 961 }
962 962 };
963 963 };
964 964
965 965
966 966 Notebook.prototype.handle_iopub_reply = function (e) {
967 967 reply = $.parseJSON(e.data);
968 968 var content = reply.content;
969 969 // console.log(reply);
970 970 var msg_type = reply.header.msg_type;
971 971 var cell = this.cell_for_msg(reply.parent_header.msg_id);
972 972 if (msg_type !== 'status' && !cell){
973 973 // message not from this notebook, but should be attached to a cell
974 974 console.log("Received IOPub message not caused by one of my cells");
975 975 console.log(reply);
976 976 return;
977 977 }
978 978 var output_types = ['stream','display_data','pyout','pyerr'];
979 979 if (output_types.indexOf(msg_type) >= 0) {
980 980 this.handle_output(cell, msg_type, content);
981 981 } else if (msg_type === 'status') {
982 982 if (content.execution_state === 'busy') {
983 983 IPython.kernel_status_widget.status_busy();
984 984 } else if (content.execution_state === 'idle') {
985 985 IPython.kernel_status_widget.status_idle();
986 986 } else if (content.execution_state === 'dead') {
987 987 this.handle_status_dead();
988 988 };
989 989 } else if (msg_type === 'clear_output') {
990 990 cell.clear_output(content.stdout, content.stderr, content.other);
991 991 };
992 992 };
993 993
994 994
995 995 Notebook.prototype.handle_status_dead = function () {
996 996 var that = this;
997 997 this.kernel.stop_channels();
998 998 var dialog = $('<div/>');
999 999 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.');
1000 1000 $(document).append(dialog);
1001 1001 dialog.dialog({
1002 1002 resizable: false,
1003 1003 modal: true,
1004 1004 title: "Dead kernel",
1005 1005 buttons : {
1006 1006 "Restart": function () {
1007 1007 that.start_kernel();
1008 1008 $(this).dialog('close');
1009 1009 },
1010 1010 "Continue running": function () {
1011 1011 $(this).dialog('close');
1012 1012 }
1013 1013 }
1014 1014 });
1015 1015 };
1016 1016
1017 1017
1018 1018 Notebook.prototype.handle_output = function (cell, msg_type, content) {
1019 1019 var json = {};
1020 1020 json.output_type = msg_type;
1021 1021 if (msg_type === "stream") {
1022 1022 json.text = content.data;
1023 1023 json.stream = content.name;
1024 1024 } else if (msg_type === "display_data") {
1025 1025 json = this.convert_mime_types(json, content.data);
1026 1026 } else if (msg_type === "pyout") {
1027 1027 json.prompt_number = content.execution_count;
1028 1028 json = this.convert_mime_types(json, content.data);
1029 1029 } else if (msg_type === "pyerr") {
1030 1030 json.ename = content.ename;
1031 1031 json.evalue = content.evalue;
1032 1032 json.traceback = content.traceback;
1033 1033 };
1034 1034 cell.append_output(json);
1035 1035 this.dirty = true;
1036 1036 };
1037 1037
1038 1038
1039 1039 Notebook.prototype.convert_mime_types = function (json, data) {
1040 1040 if (data['text/plain'] !== undefined) {
1041 1041 json.text = data['text/plain'];
1042 1042 };
1043 1043 if (data['text/html'] !== undefined) {
1044 1044 json.html = data['text/html'];
1045 1045 };
1046 1046 if (data['image/svg+xml'] !== undefined) {
1047 1047 json.svg = data['image/svg+xml'];
1048 1048 };
1049 1049 if (data['image/png'] !== undefined) {
1050 1050 json.png = data['image/png'];
1051 1051 };
1052 1052 if (data['image/jpeg'] !== undefined) {
1053 1053 json.jpeg = data['image/jpeg'];
1054 1054 };
1055 1055 if (data['text/latex'] !== undefined) {
1056 1056 json.latex = data['text/latex'];
1057 1057 };
1058 1058 if (data['application/json'] !== undefined) {
1059 1059 json.json = data['application/json'];
1060 1060 };
1061 1061 if (data['application/javascript'] !== undefined) {
1062 1062 json.javascript = data['application/javascript'];
1063 1063 }
1064 1064 return json;
1065 1065 };
1066 1066
1067 1067
1068 1068 Notebook.prototype.execute_selected_cell = function (options) {
1069 1069 // add_new: should a new cell be added if we are at the end of the nb
1070 1070 // terminal: execute in terminal mode, which stays in the current cell
1071 1071 default_options = {terminal: false, add_new: true};
1072 1072 $.extend(default_options, options);
1073 1073 var that = this;
1074 1074 var cell = that.get_selected_cell();
1075 1075 var cell_index = that.find_cell_index(cell);
1076 1076 if (cell instanceof IPython.CodeCell) {
1077 1077 cell.clear_output(true, true, true);
1078 1078 cell.set_input_prompt('*');
1079 1079 cell.element.addClass("running");
1080 1080 var code = cell.get_text();
1081 1081 var msg_id = that.kernel.execute(cell.get_text());
1082 1082 that.msg_cell_map[msg_id] = cell.cell_id;
1083 1083 } else if (cell instanceof IPython.HTMLCell) {
1084 1084 cell.render();
1085 1085 }
1086 1086 if (default_options.terminal) {
1087 1087 cell.select_all();
1088 1088 } else {
1089 1089 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
1090 1090 that.insert_cell_below('code');
1091 1091 // If we are adding a new cell at the end, scroll down to show it.
1092 1092 that.scroll_to_bottom();
1093 1093 } else {
1094 1094 that.select(cell_index+1);
1095 1095 };
1096 1096 };
1097 1097 this.dirty = true;
1098 1098 };
1099 1099
1100 1100
1101 1101 Notebook.prototype.execute_all_cells = function () {
1102 1102 var ncells = this.ncells();
1103 1103 for (var i=0; i<ncells; i++) {
1104 1104 this.select(i);
1105 1105 this.execute_selected_cell({add_new:false});
1106 1106 };
1107 1107 this.scroll_to_bottom();
1108 1108 };
1109 1109
1110 1110
1111 1111 Notebook.prototype.request_tool_tip = function (cell,func) {
1112 1112 // Feel free to shorten this logic if you are better
1113 1113 // than me in regEx
1114 1114 // basicaly you shoul be able to get xxx.xxx.xxx from
1115 1115 // something(range(10), kwarg=smth) ; xxx.xxx.xxx( firstarg, rand(234,23), kwarg1=2,
1116 1116 // remove everything between matchin bracket (need to iterate)
1117 1117 matchBracket = /\([^\(\)]+\)/g;
1118 1118 oldfunc = func;
1119 1119 func = func.replace(matchBracket,"");
1120 1120 while( oldfunc != func )
1121 1121 {
1122 1122 oldfunc = func;
1123 1123 func = func.replace(matchBracket,"");
1124 1124 }
1125 1125 // remove everythin after last open bracket
1126 1126 endBracket = /\([^\(]*$/g;
1127 1127 func = func.replace(endBracket,"");
1128 1128 var re = /[a-zA-Z._]+$/g;
1129 1129 var msg_id = this.kernel.object_info_request(re.exec(func));
1130 1130 if(typeof(msg_id)!='undefined'){
1131 1131 this.msg_cell_map[msg_id] = cell.cell_id;
1132 1132 }
1133 1133 };
1134 1134
1135 1135 Notebook.prototype.complete_cell = function (cell, line, cursor_pos) {
1136 1136 var msg_id = this.kernel.complete(line, cursor_pos);
1137 1137 this.msg_cell_map[msg_id] = cell.cell_id;
1138 1138 };
1139 1139
1140 1140 // Persistance and loading
1141 1141
1142 1142
1143 1143 Notebook.prototype.fromJSON = function (data) {
1144 1144 var ncells = this.ncells();
1145 1145 var i;
1146 1146 for (i=0; i<ncells; i++) {
1147 1147 // Always delete cell 0 as they get renumbered as they are deleted.
1148 1148 this.delete_cell(0);
1149 1149 };
1150 1150 // Save the metadata
1151 1151 this.metadata = data.metadata;
1152 1152 // Only handle 1 worksheet for now.
1153 1153 var worksheet = data.worksheets[0];
1154 1154 if (worksheet !== undefined) {
1155 1155 var new_cells = worksheet.cells;
1156 1156 ncells = new_cells.length;
1157 1157 var cell_data = null;
1158 1158 var new_cell = null;
1159 1159 for (i=0; i<ncells; i++) {
1160 1160 cell_data = new_cells[i];
1161 1161 new_cell = this.insert_cell_below(cell_data.cell_type);
1162 1162 new_cell.fromJSON(cell_data);
1163 1163 };
1164 1164 };
1165 1165 };
1166 1166
1167 1167
1168 1168 Notebook.prototype.toJSON = function () {
1169 1169 var cells = this.get_cells();
1170 1170 var ncells = cells.length;
1171 1171 cell_array = new Array(ncells);
1172 1172 for (var i=0; i<ncells; i++) {
1173 1173 cell_array[i] = cells[i].toJSON();
1174 1174 };
1175 1175 data = {
1176 1176 // Only handle 1 worksheet for now.
1177 1177 worksheets : [{cells:cell_array}],
1178 1178 metadata : this.metadata
1179 1179 };
1180 1180 return data;
1181 1181 };
1182 1182
1183 1183 Notebook.prototype.save_notebook = function () {
1184 1184 var notebook_id = IPython.save_widget.get_notebook_id();
1185 1185 var nbname = IPython.save_widget.get_notebook_name();
1186 1186 // We may want to move the name/id/nbformat logic inside toJSON?
1187 1187 var data = this.toJSON();
1188 1188 data.metadata.name = nbname;
1189 1189 data.nbformat = 2;
1190 1190 // We do the call with settings so we can set cache to false.
1191 1191 var settings = {
1192 1192 processData : false,
1193 1193 cache : false,
1194 1194 type : "PUT",
1195 1195 data : JSON.stringify(data),
1196 1196 headers : {'Content-Type': 'application/json'},
1197 1197 success : $.proxy(this.notebook_saved,this),
1198 1198 error : $.proxy(this.notebook_save_failed,this)
1199 1199 };
1200 1200 IPython.save_widget.status_saving();
1201 1201 var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id;
1202 1202 $.ajax(url, settings);
1203 1203 };
1204 1204
1205 1205
1206 1206 Notebook.prototype.notebook_saved = function (data, status, xhr) {
1207 1207 this.dirty = false;
1208 1208 IPython.save_widget.notebook_saved();
1209 1209 IPython.save_widget.status_last_saved();
1210 1210 };
1211 1211
1212 1212
1213 1213 Notebook.prototype.notebook_save_failed = function (xhr, status, error_msg) {
1214 1214 IPython.save_widget.status_save_failed();
1215 1215 };
1216 1216
1217 1217
1218 1218 Notebook.prototype.load_notebook = function () {
1219 1219 var that = this;
1220 1220 var notebook_id = IPython.save_widget.get_notebook_id();
1221 1221 // We do the call with settings so we can set cache to false.
1222 1222 var settings = {
1223 1223 processData : false,
1224 1224 cache : false,
1225 1225 type : "GET",
1226 1226 dataType : "json",
1227 1227 success : function (data, status, xhr) {
1228 1228 that.notebook_loaded(data, status, xhr);
1229 1229 }
1230 1230 };
1231 1231 IPython.save_widget.status_loading();
1232 1232 var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id;
1233 1233 $.ajax(url, settings);
1234 1234 };
1235 1235
1236 1236
1237 1237 Notebook.prototype.notebook_loaded = function (data, status, xhr) {
1238 1238 this.fromJSON(data);
1239 1239 if (this.ncells() === 0) {
1240 1240 this.insert_cell_below('code');
1241 1241 };
1242 1242 IPython.save_widget.status_last_saved();
1243 1243 IPython.save_widget.set_notebook_name(data.metadata.name);
1244 1244 this.dirty = false;
1245 1245 if (! this.read_only) {
1246 1246 this.start_kernel();
1247 1247 }
1248 1248 this.select(0);
1249 1249 this.scroll_to_top();
1250 1250 IPython.save_widget.update_url();
1251 1251 IPython.layout_manager.do_resize();
1252 1252 };
1253 1253
1254 1254 IPython.Notebook = Notebook;
1255 1255
1256 1256
1257 1257 return IPython;
1258 1258
1259 1259 }(IPython));
1260 1260
@@ -1,68 +1,69 b''
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2008-2011 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // QuickHelp button
10 10 //============================================================================
11 11
12 12 var IPython = (function (IPython) {
13 13
14 14 var QuickHelp = function (selector) {
15 15 };
16 16
17 17 QuickHelp.prototype.show_keyboard_shortcuts = function () {
18 18 // toggles display of keyboard shortcut dialog
19 19 var that = this;
20 20 if ( this.shortcut_dialog ){
21 21 // if dialog is already shown, close it
22 22 this.shortcut_dialog.dialog("close");
23 23 this.shortcut_dialog = null;
24 24 return;
25 25 }
26 26 var dialog = $('<div/>');
27 27 this.shortcut_dialog = dialog;
28 28 var shortcuts = [
29 29 {key: 'Shift-Enter', help: 'run cell'},
30 30 {key: 'Ctrl-Enter', help: 'run cell in-place'},
31 31 {key: 'Ctrl-m x', help: 'cut cell'},
32 32 {key: 'Ctrl-m c', help: 'copy cell'},
33 33 {key: 'Ctrl-m v', help: 'paste cell'},
34 34 {key: 'Ctrl-m d', help: 'delete cell'},
35 35 {key: 'Ctrl-m a', help: 'insert cell above'},
36 36 {key: 'Ctrl-m b', help: 'insert cell below'},
37 {key: 'Ctrl-m t', help: 'toggle output'},
37 {key: 'Ctrl-m o', help: 'toggle output'},
38 38 {key: 'Ctrl-m l', help: 'toggle line numbers'},
39 39 {key: 'Ctrl-m s', help: 'save notebook'},
40 40 {key: 'Ctrl-m j', help: 'move cell down'},
41 41 {key: 'Ctrl-m k', help: 'move cell up'},
42 42 {key: 'Ctrl-m y', help: 'code cell'},
43 43 {key: 'Ctrl-m m', help: 'markdown cell'},
44 {key: 'Ctrl-m t', help: 'plaintext cell'},
44 45 {key: 'Ctrl-m p', help: 'select previous'},
45 46 {key: 'Ctrl-m n', help: 'select next'},
46 47 {key: 'Ctrl-m i', help: 'interrupt kernel'},
47 48 {key: 'Ctrl-m .', help: 'restart kernel'},
48 49 {key: 'Ctrl-m h', help: 'show keyboard shortcuts'}
49 50 ];
50 51 for (var i=0; i<shortcuts.length; i++) {
51 52 dialog.append($('<div>').
52 53 append($('<span/>').addClass('shortcut_key').html(shortcuts[i].key)).
53 54 append($('<span/>').addClass('shortcut_descr').html(' : ' + shortcuts[i].help))
54 55 );
55 56 };
56 57 dialog.bind('dialogclose', function(event) {
57 58 // dialog has been closed, allow it to be drawn again.
58 59 that.shortcut_dialog = null;
59 60 });
60 61 dialog.dialog({title: 'Keyboard shortcuts', closeText: ''});
61 62 };
62 63
63 64 // Set module variables
64 65 IPython.QuickHelp = QuickHelp;
65 66
66 67 return IPython;
67 68
68 69 }(IPython));
@@ -1,351 +1,351 b''
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2008-2011 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // TextCell
10 10 //============================================================================
11 11
12 12 var IPython = (function (IPython) {
13 13
14 14 // TextCell base class
15 15
16 16 var TextCell = function (notebook) {
17 17 this.code_mirror_mode = this.code_mirror_mode || 'htmlmixed';
18 18 IPython.Cell.apply(this, arguments);
19 19 this.rendered = false;
20 20 this.cell_type = this.cell_type || 'text';
21 21 };
22 22
23 23
24 24 TextCell.prototype = new IPython.Cell();
25 25
26 26
27 27 TextCell.prototype.create_element = function () {
28 28 var cell = $("<div>").addClass('cell text_cell border-box-sizing');
29 29 cell.attr('tabindex','2');
30 30 var input_area = $('<div/>').addClass('text_cell_input border-box-sizing');
31 31 this.code_mirror = CodeMirror(input_area.get(0), {
32 32 indentUnit : 4,
33 33 mode: this.code_mirror_mode,
34 34 theme: 'default',
35 35 value: this.placeholder,
36 36 readOnly: this.read_only,
37 37 lineWrapping : true,
38 38 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
39 39 });
40 40 // The tabindex=-1 makes this div focusable.
41 41 var render_area = $('<div/>').addClass('text_cell_render border-box-sizing').
42 42 addClass('rendered_html').attr('tabindex','-1');
43 43 cell.append(input_area).append(render_area);
44 44 this.element = cell;
45 45 };
46 46
47 47
48 48 TextCell.prototype.bind_events = function () {
49 49 IPython.Cell.prototype.bind_events.apply(this);
50 50 var that = this;
51 51 this.element.keydown(function (event) {
52 52 if (event.which === 13) {
53 53 if (that.rendered) {
54 54 that.edit();
55 55 return false;
56 56 };
57 57 };
58 58 });
59 59 this.element.dblclick(function () {
60 60 that.edit();
61 61 });
62 62 };
63 63
64 64
65 65 TextCell.prototype.handle_codemirror_keyevent = function (editor, event) {
66 66 // This method gets called in CodeMirror's onKeyDown/onKeyPress
67 67 // handlers and is used to provide custom key handling. Its return
68 68 // value is used to determine if CodeMirror should ignore the event:
69 69 // true = ignore, false = don't ignore.
70 70
71 71 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
72 72 // Always ignore shift-enter in CodeMirror as we handle it.
73 73 return true;
74 74 }
75 75 return false;
76 76 };
77 77
78 78
79 79 TextCell.prototype.select = function () {
80 80 IPython.Cell.prototype.select.apply(this);
81 81 var output = this.element.find("div.text_cell_render");
82 82 output.trigger('focus');
83 83 };
84 84
85 85
86 86 TextCell.prototype.unselect = function() {
87 87 // render on selection of another cell
88 88 this.render();
89 89 IPython.Cell.prototype.unselect.apply(this);
90 90 };
91 91
92 92
93 93 TextCell.prototype.edit = function () {
94 94 if ( this.read_only ) return;
95 95 if (this.rendered === true) {
96 96 var text_cell = this.element;
97 97 var output = text_cell.find("div.text_cell_render");
98 98 output.hide();
99 99 text_cell.find('div.text_cell_input').show();
100 100 this.code_mirror.refresh();
101 101 this.code_mirror.focus();
102 102 // We used to need an additional refresh() after the focus, but
103 103 // it appears that this has been fixed in CM. This bug would show
104 104 // up on FF when a newly loaded markdown cell was edited.
105 105 this.rendered = false;
106 106 if (this.get_text() === this.placeholder) {
107 107 this.set_text('');
108 108 this.refresh();
109 109 }
110 110 }
111 111 };
112 112
113 113
114 114 // Subclasses must define render.
115 115 TextCell.prototype.render = function () {};
116 116
117 117
118 118 TextCell.prototype.get_text = function() {
119 119 return this.code_mirror.getValue();
120 120 };
121 121
122 122
123 123 TextCell.prototype.set_text = function(text) {
124 124 this.code_mirror.setValue(text);
125 125 this.code_mirror.refresh();
126 126 };
127 127
128 128
129 129 TextCell.prototype.get_rendered = function() {
130 130 return this.element.find('div.text_cell_render').html();
131 131 };
132 132
133 133
134 134 TextCell.prototype.set_rendered = function(text) {
135 135 this.element.find('div.text_cell_render').html(text);
136 136 };
137 137
138 138
139 139 TextCell.prototype.at_top = function () {
140 140 if (this.rendered) {
141 141 return true;
142 142 } else {
143 143 return false;
144 144 }
145 145 };
146 146
147 147
148 148 TextCell.prototype.at_bottom = function () {
149 149 if (this.rendered) {
150 150 return true;
151 151 } else {
152 152 return false;
153 153 }
154 154 };
155 155
156 156
157 157 TextCell.prototype.fromJSON = function (data) {
158 158 if (data.cell_type === this.cell_type) {
159 159 if (data.source !== undefined) {
160 160 this.set_text(data.source);
161 161 this.set_rendered(data.rendered || '');
162 162 this.rendered = false;
163 163 this.render();
164 164 }
165 165 }
166 166 };
167 167
168 168
169 169 TextCell.prototype.toJSON = function () {
170 170 var data = {};
171 171 data.cell_type = this.cell_type;
172 172 data.source = this.get_text();
173 173 return data;
174 174 };
175 175
176 176
177 177 // HTMLCell
178 178
179 179 var HTMLCell = function (notebook) {
180 180 this.placeholder = "Type <strong>HTML</strong> and LaTeX: $\\alpha^2$";
181 181 IPython.TextCell.apply(this, arguments);
182 182 this.cell_type = 'html';
183 183 };
184 184
185 185
186 186 HTMLCell.prototype = new TextCell();
187 187
188 188
189 189 HTMLCell.prototype.render = function () {
190 190 if (this.rendered === false) {
191 191 var text = this.get_text();
192 192 if (text === "") { text = this.placeholder; }
193 193 this.set_rendered(text);
194 194 this.typeset();
195 195 this.element.find('div.text_cell_input').hide();
196 196 this.element.find("div.text_cell_render").show();
197 197 this.rendered = true;
198 198 }
199 199 };
200 200
201 201
202 202 // MarkdownCell
203 203
204 204 var MarkdownCell = function (notebook) {
205 205 this.placeholder = "Type *Markdown* and LaTeX: $\\alpha^2$";
206 206 IPython.TextCell.apply(this, arguments);
207 207 this.cell_type = 'markdown';
208 208 };
209 209
210 210
211 211 MarkdownCell.prototype = new TextCell();
212 212
213 213
214 214 MarkdownCell.prototype.render = function () {
215 215 if (this.rendered === false) {
216 216 var text = this.get_text();
217 217 if (text === "") { text = this.placeholder; }
218 218 var html = IPython.markdown_converter.makeHtml(text);
219 219 this.set_rendered(html);
220 220 this.typeset()
221 221 this.element.find('div.text_cell_input').hide();
222 222 this.element.find("div.text_cell_render").show();
223 223 var code_snippets = this.element.find("pre > code");
224 224 code_snippets.replaceWith(function () {
225 225 var code = $(this).html();
226 226 /* Substitute br for newlines and &nbsp; for spaces
227 227 before highlighting, since prettify doesn't
228 228 preserve those on all browsers */
229 229 code = code.replace(/(\r\n|\n|\r)/gm, "<br/>");
230 230 code = code.replace(/ /gm, '&nbsp;');
231 231 code = prettyPrintOne(code);
232 232
233 233 return '<code class="prettyprint">' + code + '</code>';
234 234 });
235 235 this.rendered = true;
236 236 }
237 237 };
238 238
239 239
240 // RSTCell
240 // PlaintextCell
241 241
242 var RSTCell = function (notebook) {
243 this.placeholder = "Type *ReStructured Text* and LaTeX: $\\alpha^2$";
242 var PlaintextCell = function (notebook) {
243 this.placeholder = "Type plain text and LaTeX: $\\alpha^2$";
244 244 this.code_mirror_mode = 'rst';
245 245 IPython.TextCell.apply(this, arguments);
246 this.cell_type = 'rst';
246 this.cell_type = 'plaintext';
247 247 };
248 248
249 249
250 RSTCell.prototype = new TextCell();
250 PlaintextCell.prototype = new TextCell();
251 251
252 252
253 RSTCell.prototype.render = function () {
253 PlaintextCell.prototype.render = function () {
254 254 this.rendered = true;
255 255 this.edit();
256 256 };
257 257
258 258
259 RSTCell.prototype.select = function () {
259 PlaintextCell.prototype.select = function () {
260 260 IPython.Cell.prototype.select.apply(this);
261 261 // In some cases (inserting a new cell) we need a refresh before and
262 262 // after the focus. Not sure why this is the case.
263 263 this.code_mirror.refresh();
264 264 this.code_mirror.focus();
265 265 this.code_mirror.refresh();
266 266 };
267 267
268 268
269 RSTCell.prototype.at_top = function () {
269 PlaintextCell.prototype.at_top = function () {
270 270 var cursor = this.code_mirror.getCursor();
271 271 if (cursor.line === 0) {
272 272 return true;
273 273 } else {
274 274 return false;
275 275 }
276 276 };
277 277
278 278
279 RSTCell.prototype.at_bottom = function () {
279 PlaintextCell.prototype.at_bottom = function () {
280 280 var cursor = this.code_mirror.getCursor();
281 281 if (cursor.line === (this.code_mirror.lineCount()-1)) {
282 282 return true;
283 283 } else {
284 284 return false;
285 285 }
286 286 };
287 287
288 288
289 289 // HTMLCell
290 290
291 291 var HeadingCell = function (notebook) {
292 292 this.placeholder = "Type Heading Here";
293 293 IPython.TextCell.apply(this, arguments);
294 294 this.cell_type = 'heading';
295 295 this.level = 1;
296 296 };
297 297
298 298
299 299 HeadingCell.prototype = new TextCell();
300 300
301 301
302 302 HeadingCell.prototype.set_level = function (level) {
303 303 this.level = level;
304 304 if (this.rendered) {
305 305 this.rendered = false;
306 306 this.render();
307 307 };
308 308 };
309 309
310 310
311 311 HeadingCell.prototype.get_level = function () {
312 312 return this.level;
313 313 };
314 314
315 315
316 316 HeadingCell.prototype.set_rendered = function (text) {
317 317 var r = this.element.find("div.text_cell_render");
318 318 r.empty();
319 319 r.append($('<h'+this.level+'/>').html(text));
320 320 };
321 321
322 322
323 323 HeadingCell.prototype.get_rendered = function () {
324 324 var r = this.element.find("div.text_cell_render");
325 325 return r.children().first().html();
326 326 };
327 327
328 328
329 329 HeadingCell.prototype.render = function () {
330 330 if (this.rendered === false) {
331 331 var text = this.get_text();
332 332 if (text === "") { text = this.placeholder; }
333 333 this.set_rendered(text);
334 334 this.typeset();
335 335 this.element.find('div.text_cell_input').hide();
336 336 this.element.find("div.text_cell_render").show();
337 337 this.rendered = true;
338 338 };
339 339 };
340 340
341 341 IPython.TextCell = TextCell;
342 342 IPython.HTMLCell = HTMLCell;
343 343 IPython.MarkdownCell = MarkdownCell;
344 IPython.RSTCell = RSTCell;
344 IPython.PlaintextCell = PlaintextCell;
345 345 IPython.HeadingCell = HeadingCell;
346 346
347 347
348 348 return IPython;
349 349
350 350 }(IPython));
351 351
@@ -1,234 +1,234 b''
1 1 <!DOCTYPE HTML>
2 2 <html>
3 3
4 4 <head>
5 5 <meta charset="utf-8">
6 6
7 7 <title>IPython Notebook</title>
8 8
9 9 {% if mathjax_url %}
10 10 <script type="text/javascript" src="{{mathjax_url}}?config=TeX-AMS_HTML" charset="utf-8"></script>
11 11 {% end %}
12 12 <script type="text/javascript">
13 13 // MathJax disabled, set as null to distingish from *missing* MathJax,
14 14 // where it will be undefined, and should prompt a dialog later.
15 15 window.mathjax_url = "{{mathjax_url}}";
16 16 </script>
17 17
18 18 <link rel="stylesheet" href="{{ static_url("jquery/css/themes/base/jquery-ui.min.css") }}" type="text/css" />
19 19 <link rel="stylesheet" href="{{ static_url("codemirror/lib/codemirror.css") }}">
20 20 <link rel="stylesheet" href="{{ static_url("codemirror/theme/ipython.css") }}">
21 21
22 22 <link rel="stylesheet" href="{{ static_url("prettify/prettify.css") }}"/>
23 23
24 24 <link rel="stylesheet" href="{{ static_url("css/boilerplate.css") }}" type="text/css" />
25 25 <link rel="stylesheet" href="{{ static_url("css/layout.css") }}" type="text/css" />
26 26 <link rel="stylesheet" href="{{ static_url("css/base.css") }}" type="text/css" />
27 27 <link rel="stylesheet" href="{{ static_url("css/notebook.css") }}" type="text/css" />
28 28 <link rel="stylesheet" href="{{ static_url("css/renderedhtml.css") }}" type="text/css" />
29 29
30 30 {% comment In the notebook, the read-only flag is used to determine %}
31 31 {% comment whether to hide the side panels and switch off input %}
32 32 <meta name="read_only" content="{{read_only and not logged_in}}"/>
33 33
34 34 </head>
35 35
36 36 <body
37 37 data-project={{project}} data-notebook-id={{notebook_id}}
38 38 data-base-project-url={{base_project_url}} data-base-kernel-url={{base_kernel_url}}
39 39 >
40 40
41 41 <div id="header">
42 42 <span id="ipython_notebook"><h1><a href='..' alt='dashboard'><img src='{{static_url("ipynblogo.png")}}' alt='IPython Notebook'/></a></h1></span>
43 43 <span id="save_widget">
44 44 <span id="notebook_name"></span>
45 45 <span id="save_status"></span>
46 46 </span>
47 47
48 48 <span id="login_widget">
49 49 {% comment This is a temporary workaround to hide the logout button %}
50 50 {% comment when appropriate until notebook.html is templated %}
51 51 {% if logged_in %}
52 52 <button id="logout">Logout</button>
53 53 {% elif not logged_in and login_available %}
54 54 <button id="login">Login</button>
55 55 {% end %}
56 56 </span>
57 57
58 58 <span id="kernel_status">Idle</span>
59 59 </div>
60 60
61 61 <div id="menubar">
62 62 <ul id="menus">
63 63 <li><a href="#">File</a>
64 64 <ul>
65 65 <li id="new_notebook"><a href="#">New</a></li>
66 66 <li id="open_notebook"><a href="#">Open...</a></li>
67 67 <hr/>
68 68 <li id="copy_notebook"><a href="#">Make a Copy...</a></li>
69 69 <li id="rename_notebook"><a href="#">Rename...</a></li>
70 70 <li id="save_notebook"><a href="#">Save</a></li>
71 71 <hr/>
72 72 <li><a href="#">Download as</a>
73 73 <ul>
74 74 <li id="download_ipynb"><a href="#">IPython (.ipynb)</a></li>
75 75 <li id="download_py"><a href="#">Python (.py)</a></li>
76 76 </ul>
77 77 </li>
78 78 <hr/>
79 79 <li id="print_notebook"><a href="/{{notebook_id}}/print" target="_blank">Print View</a></li>
80 80 </ul>
81 81 </li>
82 82 <li><a href="#">Edit</a>
83 83 <ul>
84 84 <li id="cut_cell"><a href="#">Cut Cell</a></li>
85 85 <li id="copy_cell"><a href="#">Copy Cell</a></li>
86 86 <li id="paste_cell" class="ui-state-disabled"><a href="#">Paste Cell</a></li>
87 87 <li id="paste_cell_above" class="ui-state-disabled"><a href="#">Paste Cell Above</a></li>
88 88 <li id="paste_cell_below" class="ui-state-disabled"><a href="#">Paste Cell Below</a></li>
89 89 <li id="delete_cell"><a href="#">Delete</a></li>
90 90 <hr/>
91 91 <li id="split_cell"><a href="#">Split Cell</a></li>
92 92 <li id="merge_cell_above"><a href="#">Merge Cell Above</a></li>
93 93 <li id="merge_cell_below"><a href="#">Merge Cell Below</a></li>
94 94 <hr/>
95 95 <li id="move_cell_up"><a href="#">Move Cell Up</a></li>
96 96 <li id="move_cell_down"><a href="#">Move Cell Down</a></li>
97 97 <hr/>
98 98 <li id="select_previous"><a href="#">Select Previous Cell</a></li>
99 99 <li id="select_next"><a href="#">Select Next Cell</a></li>
100 100 </ul>
101 101 </li>
102 102 <li><a href="#">View</a>
103 103 <ul>
104 104 <li id="toggle_header"><a href="#">Toggle Header</a></li>
105 105 <li id="toggle_toolbar"><a href="#">Toggle Toolbar</a></li>
106 106 </ul>
107 107 </li>
108 108 <li><a href="#">Insert</a>
109 109 <ul>
110 110 <li id="insert_cell_above"><a href="#">Insert Cell Above</a></li>
111 111 <li id="insert_cell_below"><a href="#">Insert Cell Below</a></li>
112 112 </ul>
113 113 </li>
114 114 <li><a href="#">Cell</a>
115 115 <ul>
116 116 <li id="run_cell"><a href="#">Run</a></li>
117 117 <li id="run_cell_in_place"><a href="#">Run in Place</a></li>
118 118 <li id="run_all_cells"><a href="#">Run All</a></li>
119 119 <hr/>
120 120 <li id="to_code"><a href="#">Code</a></li>
121 121 <li id="to_markdown"><a href="#">Markdown </a></li>
122 <li id="to_rst"><a href="#">RST</a></li>
122 <li id="to_plaintext"><a href="#">Plaintext</a></li>
123 123 <li id="to_heading1"><a href="#">Heading 1</a></li>
124 124 <li id="to_heading2"><a href="#">Heading 2</a></li>
125 125 <li id="to_heading3"><a href="#">Heading 3</a></li>
126 126 <li id="to_heading4"><a href="#">Heading 4</a></li>
127 127 <li id="to_heading5"><a href="#">Heading 5</a></li>
128 128 <li id="to_heading6"><a href="#">Heading 6</a></li>
129 129 <hr/>
130 130 <li id="toggle_output"><a href="#">Toggle Output</a></li>
131 131 <li id="clear_all_output"><a href="#">Clear All Output</a></li>
132 132 </ul>
133 133 </li>
134 134 <li><a href="#">Kernel</a>
135 135 <ul>
136 136 <li id="int_kernel"><a href="#">Interrupt</a></li>
137 137 <li id="restart_kernel"><a href="#">Restart</a></li>
138 138 </ul>
139 139 </li>
140 140 <li><a href="#">Help</a>
141 141 <ul>
142 142 <li><a href="http://ipython.org/documentation.html" target="_blank">IPython Help</a></li>
143 143 <li><a href="http://ipython.org/ipython-doc/stable/interactive/htmlnotebook.html" target="_blank">Notebook Help</a></li>
144 144 <li id="keyboard_shortcuts"><a href="#">Keyboard Shortcuts</a></li>
145 145 <hr/>
146 146 <li><a href="http://docs.python.org" target="_blank">Python</a></li>
147 147 <li><a href="http://docs.scipy.org/doc/numpy/reference/" target="_blank">NumPy</a></li>
148 148 <li><a href="http://docs.scipy.org/doc/scipy/reference/" target="_blank">SciPy</a></li>
149 149 <li><a href="http://docs.sympy.org/dev/index.html" target="_blank">SymPy</a></li>
150 150 <li><a href="http://matplotlib.sourceforge.net/" target="_blank">Matplotlib</a></li>
151 151 </ul>
152 152 </li>
153 153 </ul>
154 154
155 155 </div>
156 156
157 157 <div id="toolbar">
158 158
159 159 <span>
160 160 <button id="save_b">Save</button>
161 161 </span>
162 162 <span id="cut_copy_paste">
163 163 <button id="cut_b" title="Cut Cell">Cut Cell</button>
164 164 <button id="copy_b" title="Copy Cell">Copy Cell</button>
165 165 <button id="paste_b" title="Paste Cell">Paste Cell</button>
166 166 </span>
167 167 <span id="move_up_down">
168 168 <button id="move_up_b" title="Move Cell Up">Move Cell Up</button>
169 169 <button id="move_down_b" title="Move Cell Down">Move Down</button>
170 170 </span>
171 171 <span id="insert_above_below">
172 172 <button id="insert_above_b" title="Insert Cell Above">Insert Cell Above</button>
173 173 <button id="insert_below_b" title="Insert Cell Below">Insert Cell Below</button>
174 174 </span>
175 175 <span id="run_int">
176 176 <button id="run_b" title="Run Cell">Run Cell</button>
177 177 <button id="interrupt_b" title="Interrupt">Interrupt</button>
178 178 </span>
179 179 <span>
180 180 <select id="cell_type">
181 181 <option value="code">Code</option>
182 182 <option value="markdown">Markdown</option>
183 183 </select>
184 184 </span>
185 185
186 186 </div>
187 187
188 188 <div id="main_app">
189 189
190 190 <div id="notebook_panel">
191 191 <div id="notebook"></div>
192 192 <div id="pager_splitter"></div>
193 193 <div id="pager"></div>
194 194 </div>
195 195
196 196 </div>
197 197
198 198 <script src="{{ static_url("jquery/js/jquery-1.7.1.min.js") }}" type="text/javascript" charset="utf-8"></script>
199 199 <script src="{{ static_url("jquery/js/jquery-ui.min.js") }}" type="text/javascript" charset="utf-8"></script>
200 200
201 201 <script src="{{ static_url("codemirror/lib/codemirror.js") }}" charset="utf-8"></script>
202 202 <script src="{{ static_url("codemirror/mode/python/python.js") }}" charset="utf-8"></script>
203 203 <script src="{{ static_url("codemirror/mode/htmlmixed/htmlmixed.js") }}" charset="utf-8"></script>
204 204 <script src="{{ static_url("codemirror/mode/xml/xml.js") }}" charset="utf-8"></script>
205 205 <script src="{{ static_url("codemirror/mode/javascript/javascript.js") }}" charset="utf-8"></script>
206 206 <script src="{{ static_url("codemirror/mode/css/css.js") }}" charset="utf-8"></script>
207 207 <script src="{{ static_url("codemirror/mode/rst/rst.js") }}" charset="utf-8"></script>
208 208 <script src="{{ static_url("codemirror/mode/markdown/markdown.js") }}" charset="utf-8"></script>
209 209
210 210 <script src="{{ static_url("pagedown/Markdown.Converter.js") }}" charset="utf-8"></script>
211 211
212 212 <script src="{{ static_url("prettify/prettify.js") }}" charset="utf-8"></script>
213 213 <script src="{{ static_url("dateformat/date.format.js") }}" charset="utf-8"></script>
214 214
215 215 <script src="{{ static_url("js/namespace.js") }}" type="text/javascript" charset="utf-8"></script>
216 216 <script src="{{ static_url("js/utils.js") }}" type="text/javascript" charset="utf-8"></script>
217 217 <script src="{{ static_url("js/cell.js") }}" type="text/javascript" charset="utf-8"></script>
218 218 <script src="{{ static_url("js/codecell.js") }}" type="text/javascript" charset="utf-8"></script>
219 219 <script src="{{ static_url("js/textcell.js") }}" type="text/javascript" charset="utf-8"></script>
220 220 <script src="{{ static_url("js/kernel.js") }}" type="text/javascript" charset="utf-8"></script>
221 221 <script src="{{ static_url("js/kernelstatus.js") }}" type="text/javascript" charset="utf-8"></script>
222 222 <script src="{{ static_url("js/layout.js") }}" type="text/javascript" charset="utf-8"></script>
223 223 <script src="{{ static_url("js/savewidget.js") }}" type="text/javascript" charset="utf-8"></script>
224 224 <script src="{{ static_url("js/quickhelp.js") }}" type="text/javascript" charset="utf-8"></script>
225 225 <script src="{{ static_url("js/loginwidget.js") }}" type="text/javascript" charset="utf-8"></script>
226 226 <script src="{{ static_url("js/pager.js") }}" type="text/javascript" charset="utf-8"></script>
227 227 <script src="{{ static_url("js/menubar.js") }}" type="text/javascript" charset="utf-8"></script>
228 228 <script src="{{ static_url("js/toolbar.js") }}" type="text/javascript" charset="utf-8"></script>
229 229 <script src="{{ static_url("js/notebook.js") }}" type="text/javascript" charset="utf-8"></script>
230 230 <script src="{{ static_url("js/notebookmain.js") }}" type="text/javascript" charset="utf-8"></script>
231 231
232 232 </body>
233 233
234 234 </html>
General Comments 0
You need to be logged in to leave comments. Login now