##// END OF EJS Templates
Heading/plaintext cells now wired up to toolbar UI.
Brian Granger -
Show More
@@ -1,1260 +1,1265 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 138 } else if (event.which === 84 && that.control_key_active) {
139 // To Plaintext = r
139 // To Plaintext = t
140 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 173 } else if (event.which === 79 && that.control_key_active) {
174 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 IPython.toolbar.set_cell_type(cell.cell_type);
404 if (cell.cell_type === 'heading') {
405 IPython.toolbar.set_cell_type(cell.cell_type+cell.level);
406 } else {
407 IPython.toolbar.set_cell_type(cell.cell_type)
408 }
405 409 };
406 410 return this;
407 411 };
408 412
409 413
410 414 Notebook.prototype.select_next = function () {
411 415 var index = this.get_selected_index();
412 416 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
413 417 this.select(index+1);
414 418 };
415 419 return this;
416 420 };
417 421
418 422
419 423 Notebook.prototype.select_prev = function () {
420 424 var index = this.get_selected_index();
421 425 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
422 426 this.select(index-1);
423 427 };
424 428 return this;
425 429 };
426 430
427 431
428 432 // Cell movement
429 433
430 434 Notebook.prototype.move_cell_up = function (index) {
431 435 var i = this.index_or_selected();
432 436 if (i !== null && i < this.ncells() && i > 0) {
433 437 var pivot = this.get_cell_element(i-1);
434 438 var tomove = this.get_cell_element(i);
435 439 if (pivot !== null && tomove !== null) {
436 440 tomove.detach();
437 441 pivot.before(tomove);
438 442 this.select(i-1);
439 443 };
440 444 };
441 445 this.dirty = true;
442 446 return this;
443 447 };
444 448
445 449
446 450 Notebook.prototype.move_cell_down = function (index) {
447 451 var i = this.index_or_selected();
448 452 if (i !== null && i < (this.ncells()-1) && i >= 0) {
449 453 var pivot = this.get_cell_element(i+1);
450 454 var tomove = this.get_cell_element(i);
451 455 if (pivot !== null && tomove !== null) {
452 456 tomove.detach();
453 457 pivot.after(tomove);
454 458 this.select(i+1);
455 459 };
456 460 };
457 461 this.dirty = true;
458 462 return this;
459 463 };
460 464
461 465
462 466 Notebook.prototype.sort_cells = function () {
463 467 // This is not working right now. Calling this will actually crash
464 468 // the browser. I think there is an infinite loop in here...
465 469 var ncells = this.ncells();
466 470 var sindex = this.get_selected_index();
467 471 var swapped;
468 472 do {
469 473 swapped = false;
470 474 for (var i=1; i<ncells; i++) {
471 475 current = this.get_cell(i);
472 476 previous = this.get_cell(i-1);
473 477 if (previous.input_prompt_number > current.input_prompt_number) {
474 478 this.move_cell_up(i);
475 479 swapped = true;
476 480 };
477 481 };
478 482 } while (swapped);
479 483 this.select(sindex);
480 484 return this;
481 485 };
482 486
483 487 // Insertion, deletion.
484 488
485 489 Notebook.prototype.delete_cell = function (index) {
486 490 var i = this.index_or_selected(index);
487 491 if (this.is_valid_cell_index(i)) {
488 492 var ce = this.get_cell_element(i);
489 493 ce.remove();
490 494 if (i === (this.ncells())) {
491 495 this.select(i-1);
492 496 } else {
493 497 this.select(i);
494 498 };
495 499 this.dirty = true;
496 500 };
497 501 return this;
498 502 };
499 503
500 504
501 505 Notebook.prototype.insert_cell_below = function (type, index) {
502 506 // type = ('code','html','markdown')
503 507 // index = cell index or undefined to insert below selected
504 508 index = this.index_or_selected(index);
505 509 var cell = null;
506 510 if (this.ncells() === 0 || this.is_valid_cell_index(index)) {
507 511 if (type === 'code') {
508 512 cell = new IPython.CodeCell(this);
509 513 cell.set_input_prompt();
510 514 } else if (type === 'markdown') {
511 515 cell = new IPython.MarkdownCell(this);
512 516 } else if (type === 'html') {
513 517 cell = new IPython.HTMLCell(this);
514 518 } else if (type === 'plaintext') {
515 519 cell = new IPython.PlaintextCell(this);
516 520 } else if (type === 'heading') {
517 521 cell = new IPython.HeadingCell(this);
518 522 };
519 523 if (cell !== null) {
520 524 if (this.ncells() === 0) {
521 525 this.element.find('div.end_space').before(cell.element);
522 526 } else if (this.is_valid_cell_index(index)) {
523 527 this.get_cell_element(index).after(cell.element);
524 528 };
525 529 cell.render();
526 530 this.select(this.find_cell_index(cell));
527 531 this.dirty = true;
528 532 return cell;
529 533 };
530 534 };
531 535 return cell;
532 536 };
533 537
534 538
535 539 Notebook.prototype.insert_cell_above = function (type, index) {
536 540 // type = ('code','html','markdown')
537 541 // index = cell index or undefined to insert above selected
538 542 index = this.index_or_selected(index);
539 543 var cell = null;
540 544 if (this.ncells() === 0 || this.is_valid_cell_index(index)) {
541 545 if (type === 'code') {
542 546 cell = new IPython.CodeCell(this);
543 547 cell.set_input_prompt();
544 548 } else if (type === 'markdown') {
545 549 cell = new IPython.MarkdownCell(this);
546 550 } else if (type === 'html') {
547 551 cell = new IPython.HTMLCell(this);
548 552 } else if (type === 'plaintext') {
549 553 cell = new IPython.PlaintextCell(this);
550 554 } else if (type === 'heading') {
551 555 cell = new IPython.HeadingCell(this);
552 556 };
553 557 if (cell !== null) {
554 558 if (this.ncells() === 0) {
555 559 this.element.find('div.end_space').before(cell.element);
556 560 } else if (this.is_valid_cell_index(index)) {
557 561 this.get_cell_element(index).before(cell.element);
558 562 };
559 563 cell.render();
560 564 this.select(this.find_cell_index(cell));
561 565 this.dirty = true;
562 566 return cell;
563 567 };
564 568 };
565 569 return cell;
566 570 };
567 571
568 572
569 573 Notebook.prototype.to_code = function (index) {
570 574 var i = this.index_or_selected(index);
571 575 if (this.is_valid_cell_index(i)) {
572 576 var source_element = this.get_cell_element(i);
573 577 var source_cell = source_element.data("cell");
574 578 if (!(source_cell instanceof IPython.CodeCell)) {
575 579 target_cell = this.insert_cell_below('code',i);
576 580 var text = source_cell.get_text();
577 581 if (text === source_cell.placeholder) {
578 582 text = '';
579 583 }
580 584 target_cell.set_text(text);
581 585 source_element.remove();
582 586 this.dirty = true;
583 587 };
584 588 };
585 589 };
586 590
587 591
588 592 Notebook.prototype.to_markdown = function (index) {
589 593 var i = this.index_or_selected(index);
590 594 if (this.is_valid_cell_index(i)) {
591 595 var source_element = this.get_cell_element(i);
592 596 var source_cell = source_element.data("cell");
593 597 if (!(source_cell instanceof IPython.MarkdownCell)) {
594 598 target_cell = this.insert_cell_below('markdown',i);
595 599 var text = source_cell.get_text();
596 600 if (text === source_cell.placeholder) {
597 601 text = '';
598 602 };
599 603 // The edit must come before the set_text.
600 604 target_cell.edit();
601 605 target_cell.set_text(text);
602 606 source_element.remove();
603 607 this.dirty = true;
604 608 };
605 609 };
606 610 };
607 611
608 612
609 613 Notebook.prototype.to_html = function (index) {
610 614 var i = this.index_or_selected(index);
611 615 if (this.is_valid_cell_index(i)) {
612 616 var source_element = this.get_cell_element(i);
613 617 var source_cell = source_element.data("cell");
614 618 var target_cell = null;
615 619 if (!(source_cell instanceof IPython.HTMLCell)) {
616 620 target_cell = this.insert_cell_below('html',i);
617 621 var text = source_cell.get_text();
618 622 if (text === source_cell.placeholder) {
619 623 text = '';
620 624 };
621 625 // The edit must come before the set_text.
622 626 target_cell.edit();
623 627 target_cell.set_text(text);
624 628 source_element.remove();
625 629 this.dirty = true;
626 630 };
627 631 };
628 632 };
629 633
630 634
631 635 Notebook.prototype.to_plaintext = function (index) {
632 636 var i = this.index_or_selected(index);
633 637 if (this.is_valid_cell_index(i)) {
634 638 var source_element = this.get_cell_element(i);
635 639 var source_cell = source_element.data("cell");
636 640 var target_cell = null;
637 641 if (!(source_cell instanceof IPython.PlaintextCell)) {
638 642 target_cell = this.insert_cell_below('plaintext',i);
639 643 var text = source_cell.get_text();
640 644 if (text === source_cell.placeholder) {
641 645 text = '';
642 646 };
643 647 // The edit must come before the set_text.
644 648 target_cell.edit();
645 649 target_cell.set_text(text);
646 650 source_element.remove();
647 651 this.dirty = true;
648 652 };
649 653 };
650 654 };
651 655
652 656
653 657 Notebook.prototype.to_heading = function (index, level) {
654 658 level = level || 1;
655 659 var i = this.index_or_selected(index);
656 660 if (this.is_valid_cell_index(i)) {
657 661 var source_element = this.get_cell_element(i);
658 662 var source_cell = source_element.data("cell");
659 663 var target_cell = null;
660 664 if (source_cell instanceof IPython.HeadingCell) {
661 665 source_cell.set_level(level);
662 666 } else {
663 667 target_cell = this.insert_cell_below('heading',i);
664 668 var text = source_cell.get_text();
665 669 if (text === source_cell.placeholder) {
666 670 text = '';
667 671 };
668 672 // The edit must come before the set_text.
669 673 target_cell.set_level(level);
670 674 target_cell.edit();
671 675 target_cell.set_text(text);
672 676 source_element.remove();
673 677 this.dirty = true;
674 678 };
679 IPython.toolbar.set_cell_type("heading"+level);
675 680 };
676 681 };
677 682
678 683
679 684 // Cut/Copy/Paste
680 685
681 686 Notebook.prototype.enable_paste = function () {
682 687 var that = this;
683 688 if (!this.paste_enabled) {
684 689 $('#paste_cell').removeClass('ui-state-disabled')
685 690 .on('click', function () {that.paste_cell();});
686 691 $('#paste_cell_above').removeClass('ui-state-disabled')
687 692 .on('click', function () {that.paste_cell_above();});
688 693 $('#paste_cell_below').removeClass('ui-state-disabled')
689 694 .on('click', function () {that.paste_cell_below();});
690 695 this.paste_enabled = true;
691 696 };
692 697 };
693 698
694 699
695 700 Notebook.prototype.disable_paste = function () {
696 701 if (this.paste_enabled) {
697 702 $('#paste_cell').addClass('ui-state-disabled').off('click');
698 703 $('#paste_cell_above').addClass('ui-state-disabled').off('click');
699 704 $('#paste_cell_below').addClass('ui-state-disabled').off('click');
700 705 this.paste_enabled = false;
701 706 };
702 707 };
703 708
704 709
705 710 Notebook.prototype.cut_cell = function () {
706 711 this.copy_cell();
707 712 this.delete_cell();
708 713 }
709 714
710 715 Notebook.prototype.copy_cell = function () {
711 716 var cell = this.get_selected_cell();
712 717 this.clipboard = cell.toJSON();
713 718 this.enable_paste();
714 719 };
715 720
716 721
717 722 Notebook.prototype.paste_cell = function () {
718 723 if (this.clipboard !== null && this.paste_enabled) {
719 724 var cell_data = this.clipboard;
720 725 var new_cell = this.insert_cell_above(cell_data.cell_type);
721 726 new_cell.fromJSON(cell_data);
722 727 old_cell = this.get_next_cell(new_cell);
723 728 this.delete_cell(this.find_cell_index(old_cell));
724 729 this.select(this.find_cell_index(new_cell));
725 730 };
726 731 };
727 732
728 733
729 734 Notebook.prototype.paste_cell_above = function () {
730 735 if (this.clipboard !== null && this.paste_enabled) {
731 736 var cell_data = this.clipboard;
732 737 var new_cell = this.insert_cell_above(cell_data.cell_type);
733 738 new_cell.fromJSON(cell_data);
734 739 };
735 740 };
736 741
737 742
738 743 Notebook.prototype.paste_cell_below = function () {
739 744 if (this.clipboard !== null && this.paste_enabled) {
740 745 var cell_data = this.clipboard;
741 746 var new_cell = this.insert_cell_below(cell_data.cell_type);
742 747 new_cell.fromJSON(cell_data);
743 748 };
744 749 };
745 750
746 751
747 752 // Split/merge
748 753
749 754 Notebook.prototype.split_cell = function () {
750 755 // Todo: implement spliting for other cell types.
751 756 var cell = this.get_selected_cell();
752 757 if (cell.is_splittable()) {
753 758 texta = cell.get_pre_cursor();
754 759 textb = cell.get_post_cursor();
755 760 if (cell instanceof IPython.CodeCell) {
756 761 cell.set_text(texta);
757 762 var new_cell = this.insert_cell_below('code');
758 763 new_cell.set_text(textb);
759 764 } else if (cell instanceof IPython.MarkdownCell) {
760 765 cell.set_text(texta);
761 766 cell.render();
762 767 var new_cell = this.insert_cell_below('markdown');
763 768 new_cell.edit(); // editor must be visible to call set_text
764 769 new_cell.set_text(textb);
765 770 new_cell.render();
766 771 } else if (cell instanceof IPython.HTMLCell) {
767 772 cell.set_text(texta);
768 773 cell.render();
769 774 var new_cell = this.insert_cell_below('html');
770 775 new_cell.edit(); // editor must be visible to call set_text
771 776 new_cell.set_text(textb);
772 777 new_cell.render();
773 778 };
774 779 };
775 780 };
776 781
777 782
778 783 Notebook.prototype.merge_cell_above = function () {
779 784 var index = this.get_selected_index();
780 785 var cell = this.get_cell(index);
781 786 if (index > 0) {
782 787 upper_cell = this.get_cell(index-1);
783 788 upper_text = upper_cell.get_text();
784 789 text = cell.get_text();
785 790 if (cell instanceof IPython.CodeCell) {
786 791 cell.set_text(upper_text+'\n'+text);
787 792 } else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) {
788 793 cell.edit();
789 794 cell.set_text(upper_text+'\n'+text);
790 795 cell.render();
791 796 };
792 797 this.delete_cell(index-1);
793 798 this.select(this.find_cell_index(cell));
794 799 };
795 800 };
796 801
797 802
798 803 Notebook.prototype.merge_cell_below = function () {
799 804 var index = this.get_selected_index();
800 805 var cell = this.get_cell(index);
801 806 if (index < this.ncells()-1) {
802 807 lower_cell = this.get_cell(index+1);
803 808 lower_text = lower_cell.get_text();
804 809 text = cell.get_text();
805 810 if (cell instanceof IPython.CodeCell) {
806 811 cell.set_text(text+'\n'+lower_text);
807 812 } else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) {
808 813 cell.edit();
809 814 cell.set_text(text+'\n'+lower_text);
810 815 cell.render();
811 816 };
812 817 this.delete_cell(index+1);
813 818 this.select(this.find_cell_index(cell));
814 819 };
815 820 };
816 821
817 822
818 823 // Cell collapsing and output clearing
819 824
820 825 Notebook.prototype.collapse = function (index) {
821 826 var i = this.index_or_selected(index);
822 827 this.get_cell(i).collapse();
823 828 this.dirty = true;
824 829 };
825 830
826 831
827 832 Notebook.prototype.expand = function (index) {
828 833 var i = this.index_or_selected(index);
829 834 this.get_cell(i).expand();
830 835 this.dirty = true;
831 836 };
832 837
833 838
834 839 Notebook.prototype.toggle_output = function (index) {
835 840 var i = this.index_or_selected(index);
836 841 this.get_cell(i).toggle_output();
837 842 this.dirty = true;
838 843 };
839 844
840 845
841 846 Notebook.prototype.set_timebeforetooltip = function (time) {
842 847 this.time_before_tooltip = time;
843 848 };
844 849
845 850
846 851 Notebook.prototype.set_tooltipontab = function (state) {
847 852 this.tooltip_on_tab = state;
848 853 };
849 854
850 855
851 856 Notebook.prototype.set_smartcompleter = function (state) {
852 857 this.smart_completer = state;
853 858 };
854 859
855 860
856 861 Notebook.prototype.clear_all_output = function () {
857 862 var ncells = this.ncells();
858 863 var cells = this.get_cells();
859 864 for (var i=0; i<ncells; i++) {
860 865 if (cells[i] instanceof IPython.CodeCell) {
861 866 cells[i].clear_output(true,true,true);
862 867 }
863 868 };
864 869 this.dirty = true;
865 870 };
866 871
867 872
868 873 // Other cell functions: line numbers, ...
869 874
870 875 Notebook.prototype.cell_toggle_line_numbers = function() {
871 876 this.get_selected_cell().toggle_line_numbers();
872 877 };
873 878
874 879 // Kernel related things
875 880
876 881 Notebook.prototype.start_kernel = function () {
877 882 this.kernel = new IPython.Kernel();
878 883 var notebook_id = IPython.save_widget.get_notebook_id();
879 884 this.kernel.start(notebook_id, $.proxy(this.kernel_started, this));
880 885 };
881 886
882 887
883 888 Notebook.prototype.restart_kernel = function () {
884 889 var that = this;
885 890 var notebook_id = IPython.save_widget.get_notebook_id();
886 891
887 892 var dialog = $('<div/>');
888 893 dialog.html('Do you want to restart the current kernel? You will lose all variables defined in it.');
889 894 $(document).append(dialog);
890 895 dialog.dialog({
891 896 resizable: false,
892 897 modal: true,
893 898 title: "Restart kernel or continue running?",
894 899 closeText: '',
895 900 buttons : {
896 901 "Restart": function () {
897 902 that.kernel.restart($.proxy(that.kernel_started, that));
898 903 $(this).dialog('close');
899 904 },
900 905 "Continue running": function () {
901 906 $(this).dialog('close');
902 907 }
903 908 }
904 909 });
905 910 };
906 911
907 912
908 913 Notebook.prototype.kernel_started = function () {
909 914 console.log("Kernel started: ", this.kernel.kernel_id);
910 915 this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
911 916 this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
912 917 };
913 918
914 919
915 920 Notebook.prototype.handle_shell_reply = function (e) {
916 921 reply = $.parseJSON(e.data);
917 922 var header = reply.header;
918 923 var content = reply.content;
919 924 var msg_type = header.msg_type;
920 925 // console.log(reply);
921 926 var cell = this.cell_for_msg(reply.parent_header.msg_id);
922 927 if (msg_type === "execute_reply") {
923 928 cell.set_input_prompt(content.execution_count);
924 929 cell.element.removeClass("running");
925 930 this.dirty = true;
926 931 } else if (msg_type === "complete_reply") {
927 932 cell.finish_completing(content.matched_text, content.matches);
928 933 } else if (msg_type === "object_info_reply"){
929 934 //console.log('back from object_info_request : ')
930 935 rep = reply.content;
931 936 if(rep.found)
932 937 {
933 938 cell.finish_tooltip(rep);
934 939 }
935 940 } else {
936 941 //console.log("unknown reply:"+msg_type);
937 942 }
938 943 // when having a rely from object_info_reply,
939 944 // no payload so no nned to handle it
940 945 if(typeof(content.payload)!='undefined') {
941 946 var payload = content.payload || [];
942 947 this.handle_payload(cell, payload);
943 948 }
944 949 };
945 950
946 951
947 952 Notebook.prototype.handle_payload = function (cell, payload) {
948 953 var l = payload.length;
949 954 for (var i=0; i<l; i++) {
950 955 if (payload[i].source === 'IPython.zmq.page.page') {
951 956 if (payload[i].text.trim() !== '') {
952 957 IPython.pager.clear();
953 958 IPython.pager.expand();
954 959 IPython.pager.append_text(payload[i].text);
955 960 }
956 961 } else if (payload[i].source === 'IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input') {
957 962 var index = this.find_cell_index(cell);
958 963 var new_cell = this.insert_cell_below('code',index);
959 964 new_cell.set_text(payload[i].text);
960 965 this.dirty = true;
961 966 }
962 967 };
963 968 };
964 969
965 970
966 971 Notebook.prototype.handle_iopub_reply = function (e) {
967 972 reply = $.parseJSON(e.data);
968 973 var content = reply.content;
969 974 // console.log(reply);
970 975 var msg_type = reply.header.msg_type;
971 976 var cell = this.cell_for_msg(reply.parent_header.msg_id);
972 977 if (msg_type !== 'status' && !cell){
973 978 // message not from this notebook, but should be attached to a cell
974 979 console.log("Received IOPub message not caused by one of my cells");
975 980 console.log(reply);
976 981 return;
977 982 }
978 983 var output_types = ['stream','display_data','pyout','pyerr'];
979 984 if (output_types.indexOf(msg_type) >= 0) {
980 985 this.handle_output(cell, msg_type, content);
981 986 } else if (msg_type === 'status') {
982 987 if (content.execution_state === 'busy') {
983 988 IPython.kernel_status_widget.status_busy();
984 989 } else if (content.execution_state === 'idle') {
985 990 IPython.kernel_status_widget.status_idle();
986 991 } else if (content.execution_state === 'dead') {
987 992 this.handle_status_dead();
988 993 };
989 994 } else if (msg_type === 'clear_output') {
990 995 cell.clear_output(content.stdout, content.stderr, content.other);
991 996 };
992 997 };
993 998
994 999
995 1000 Notebook.prototype.handle_status_dead = function () {
996 1001 var that = this;
997 1002 this.kernel.stop_channels();
998 1003 var dialog = $('<div/>');
999 1004 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 1005 $(document).append(dialog);
1001 1006 dialog.dialog({
1002 1007 resizable: false,
1003 1008 modal: true,
1004 1009 title: "Dead kernel",
1005 1010 buttons : {
1006 1011 "Restart": function () {
1007 1012 that.start_kernel();
1008 1013 $(this).dialog('close');
1009 1014 },
1010 1015 "Continue running": function () {
1011 1016 $(this).dialog('close');
1012 1017 }
1013 1018 }
1014 1019 });
1015 1020 };
1016 1021
1017 1022
1018 1023 Notebook.prototype.handle_output = function (cell, msg_type, content) {
1019 1024 var json = {};
1020 1025 json.output_type = msg_type;
1021 1026 if (msg_type === "stream") {
1022 1027 json.text = content.data;
1023 1028 json.stream = content.name;
1024 1029 } else if (msg_type === "display_data") {
1025 1030 json = this.convert_mime_types(json, content.data);
1026 1031 } else if (msg_type === "pyout") {
1027 1032 json.prompt_number = content.execution_count;
1028 1033 json = this.convert_mime_types(json, content.data);
1029 1034 } else if (msg_type === "pyerr") {
1030 1035 json.ename = content.ename;
1031 1036 json.evalue = content.evalue;
1032 1037 json.traceback = content.traceback;
1033 1038 };
1034 1039 cell.append_output(json);
1035 1040 this.dirty = true;
1036 1041 };
1037 1042
1038 1043
1039 1044 Notebook.prototype.convert_mime_types = function (json, data) {
1040 1045 if (data['text/plain'] !== undefined) {
1041 1046 json.text = data['text/plain'];
1042 1047 };
1043 1048 if (data['text/html'] !== undefined) {
1044 1049 json.html = data['text/html'];
1045 1050 };
1046 1051 if (data['image/svg+xml'] !== undefined) {
1047 1052 json.svg = data['image/svg+xml'];
1048 1053 };
1049 1054 if (data['image/png'] !== undefined) {
1050 1055 json.png = data['image/png'];
1051 1056 };
1052 1057 if (data['image/jpeg'] !== undefined) {
1053 1058 json.jpeg = data['image/jpeg'];
1054 1059 };
1055 1060 if (data['text/latex'] !== undefined) {
1056 1061 json.latex = data['text/latex'];
1057 1062 };
1058 1063 if (data['application/json'] !== undefined) {
1059 1064 json.json = data['application/json'];
1060 1065 };
1061 1066 if (data['application/javascript'] !== undefined) {
1062 1067 json.javascript = data['application/javascript'];
1063 1068 }
1064 1069 return json;
1065 1070 };
1066 1071
1067 1072
1068 1073 Notebook.prototype.execute_selected_cell = function (options) {
1069 1074 // add_new: should a new cell be added if we are at the end of the nb
1070 1075 // terminal: execute in terminal mode, which stays in the current cell
1071 1076 default_options = {terminal: false, add_new: true};
1072 1077 $.extend(default_options, options);
1073 1078 var that = this;
1074 1079 var cell = that.get_selected_cell();
1075 1080 var cell_index = that.find_cell_index(cell);
1076 1081 if (cell instanceof IPython.CodeCell) {
1077 1082 cell.clear_output(true, true, true);
1078 1083 cell.set_input_prompt('*');
1079 1084 cell.element.addClass("running");
1080 1085 var code = cell.get_text();
1081 1086 var msg_id = that.kernel.execute(cell.get_text());
1082 1087 that.msg_cell_map[msg_id] = cell.cell_id;
1083 1088 } else if (cell instanceof IPython.HTMLCell) {
1084 1089 cell.render();
1085 1090 }
1086 1091 if (default_options.terminal) {
1087 1092 cell.select_all();
1088 1093 } else {
1089 1094 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
1090 1095 that.insert_cell_below('code');
1091 1096 // If we are adding a new cell at the end, scroll down to show it.
1092 1097 that.scroll_to_bottom();
1093 1098 } else {
1094 1099 that.select(cell_index+1);
1095 1100 };
1096 1101 };
1097 1102 this.dirty = true;
1098 1103 };
1099 1104
1100 1105
1101 1106 Notebook.prototype.execute_all_cells = function () {
1102 1107 var ncells = this.ncells();
1103 1108 for (var i=0; i<ncells; i++) {
1104 1109 this.select(i);
1105 1110 this.execute_selected_cell({add_new:false});
1106 1111 };
1107 1112 this.scroll_to_bottom();
1108 1113 };
1109 1114
1110 1115
1111 1116 Notebook.prototype.request_tool_tip = function (cell,func) {
1112 1117 // Feel free to shorten this logic if you are better
1113 1118 // than me in regEx
1114 1119 // basicaly you shoul be able to get xxx.xxx.xxx from
1115 1120 // something(range(10), kwarg=smth) ; xxx.xxx.xxx( firstarg, rand(234,23), kwarg1=2,
1116 1121 // remove everything between matchin bracket (need to iterate)
1117 1122 matchBracket = /\([^\(\)]+\)/g;
1118 1123 oldfunc = func;
1119 1124 func = func.replace(matchBracket,"");
1120 1125 while( oldfunc != func )
1121 1126 {
1122 1127 oldfunc = func;
1123 1128 func = func.replace(matchBracket,"");
1124 1129 }
1125 1130 // remove everythin after last open bracket
1126 1131 endBracket = /\([^\(]*$/g;
1127 1132 func = func.replace(endBracket,"");
1128 1133 var re = /[a-zA-Z._]+$/g;
1129 1134 var msg_id = this.kernel.object_info_request(re.exec(func));
1130 1135 if(typeof(msg_id)!='undefined'){
1131 1136 this.msg_cell_map[msg_id] = cell.cell_id;
1132 1137 }
1133 1138 };
1134 1139
1135 1140 Notebook.prototype.complete_cell = function (cell, line, cursor_pos) {
1136 1141 var msg_id = this.kernel.complete(line, cursor_pos);
1137 1142 this.msg_cell_map[msg_id] = cell.cell_id;
1138 1143 };
1139 1144
1140 1145 // Persistance and loading
1141 1146
1142 1147
1143 1148 Notebook.prototype.fromJSON = function (data) {
1144 1149 var ncells = this.ncells();
1145 1150 var i;
1146 1151 for (i=0; i<ncells; i++) {
1147 1152 // Always delete cell 0 as they get renumbered as they are deleted.
1148 1153 this.delete_cell(0);
1149 1154 };
1150 1155 // Save the metadata
1151 1156 this.metadata = data.metadata;
1152 1157 // Only handle 1 worksheet for now.
1153 1158 var worksheet = data.worksheets[0];
1154 1159 if (worksheet !== undefined) {
1155 1160 var new_cells = worksheet.cells;
1156 1161 ncells = new_cells.length;
1157 1162 var cell_data = null;
1158 1163 var new_cell = null;
1159 1164 for (i=0; i<ncells; i++) {
1160 1165 cell_data = new_cells[i];
1161 1166 new_cell = this.insert_cell_below(cell_data.cell_type);
1162 1167 new_cell.fromJSON(cell_data);
1163 1168 };
1164 1169 };
1165 1170 };
1166 1171
1167 1172
1168 1173 Notebook.prototype.toJSON = function () {
1169 1174 var cells = this.get_cells();
1170 1175 var ncells = cells.length;
1171 1176 cell_array = new Array(ncells);
1172 1177 for (var i=0; i<ncells; i++) {
1173 1178 cell_array[i] = cells[i].toJSON();
1174 1179 };
1175 1180 data = {
1176 1181 // Only handle 1 worksheet for now.
1177 1182 worksheets : [{cells:cell_array}],
1178 1183 metadata : this.metadata
1179 1184 };
1180 1185 return data;
1181 1186 };
1182 1187
1183 1188 Notebook.prototype.save_notebook = function () {
1184 1189 var notebook_id = IPython.save_widget.get_notebook_id();
1185 1190 var nbname = IPython.save_widget.get_notebook_name();
1186 1191 // We may want to move the name/id/nbformat logic inside toJSON?
1187 1192 var data = this.toJSON();
1188 1193 data.metadata.name = nbname;
1189 1194 data.nbformat = 2;
1190 1195 // We do the call with settings so we can set cache to false.
1191 1196 var settings = {
1192 1197 processData : false,
1193 1198 cache : false,
1194 1199 type : "PUT",
1195 1200 data : JSON.stringify(data),
1196 1201 headers : {'Content-Type': 'application/json'},
1197 1202 success : $.proxy(this.notebook_saved,this),
1198 1203 error : $.proxy(this.notebook_save_failed,this)
1199 1204 };
1200 1205 IPython.save_widget.status_saving();
1201 1206 var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id;
1202 1207 $.ajax(url, settings);
1203 1208 };
1204 1209
1205 1210
1206 1211 Notebook.prototype.notebook_saved = function (data, status, xhr) {
1207 1212 this.dirty = false;
1208 1213 IPython.save_widget.notebook_saved();
1209 1214 IPython.save_widget.status_last_saved();
1210 1215 };
1211 1216
1212 1217
1213 1218 Notebook.prototype.notebook_save_failed = function (xhr, status, error_msg) {
1214 1219 IPython.save_widget.status_save_failed();
1215 1220 };
1216 1221
1217 1222
1218 1223 Notebook.prototype.load_notebook = function () {
1219 1224 var that = this;
1220 1225 var notebook_id = IPython.save_widget.get_notebook_id();
1221 1226 // We do the call with settings so we can set cache to false.
1222 1227 var settings = {
1223 1228 processData : false,
1224 1229 cache : false,
1225 1230 type : "GET",
1226 1231 dataType : "json",
1227 1232 success : function (data, status, xhr) {
1228 1233 that.notebook_loaded(data, status, xhr);
1229 1234 }
1230 1235 };
1231 1236 IPython.save_widget.status_loading();
1232 1237 var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id;
1233 1238 $.ajax(url, settings);
1234 1239 };
1235 1240
1236 1241
1237 1242 Notebook.prototype.notebook_loaded = function (data, status, xhr) {
1238 1243 this.fromJSON(data);
1239 1244 if (this.ncells() === 0) {
1240 1245 this.insert_cell_below('code');
1241 1246 };
1242 1247 IPython.save_widget.status_last_saved();
1243 1248 IPython.save_widget.set_notebook_name(data.metadata.name);
1244 1249 this.dirty = false;
1245 1250 if (! this.read_only) {
1246 1251 this.start_kernel();
1247 1252 }
1248 1253 this.select(0);
1249 1254 this.scroll_to_top();
1250 1255 IPython.save_widget.update_url();
1251 1256 IPython.layout_manager.do_resize();
1252 1257 };
1253 1258
1254 1259 IPython.Notebook = Notebook;
1255 1260
1256 1261
1257 1262 return IPython;
1258 1263
1259 1264 }(IPython));
1260 1265
@@ -1,132 +1,146 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 // ToolBar
10 10 //============================================================================
11 11
12 12 var IPython = (function (IPython) {
13 13
14 14 var ToolBar = 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 ToolBar.prototype.style = function () {
25 25 this.element.addClass('border-box-sizing');
26 26 this.element.find('#cell_type').addClass('ui-widget ui-widget-content');
27 27 this.element.find('#save_b').button({
28 28 icons : {primary: 'ui-icon-disk'},
29 29 text : false
30 30 });
31 31 this.element.find('#cut_b').button({
32 32 icons: {primary: 'ui-icon-scissors'},
33 33 text : false
34 34 });
35 35 this.element.find('#copy_b').button({
36 36 icons: {primary: 'ui-icon-copy'},
37 37 text : false
38 38 });
39 39 this.element.find('#paste_b').button({
40 40 icons: {primary: 'ui-icon-clipboard'},
41 41 text : false
42 42 });
43 43 this.element.find('#cut_copy_paste').buttonset();
44 44 this.element.find('#move_up_b').button({
45 45 icons: {primary: 'ui-icon-arrowthick-1-n'},
46 46 text : false
47 47 });
48 48 this.element.find('#move_down_b').button({
49 49 icons: {primary: 'ui-icon-arrowthick-1-s'},
50 50 text : false
51 51 });
52 52 this.element.find('#move_up_down').buttonset();
53 53 this.element.find('#insert_above_b').button({
54 54 icons: {primary: 'ui-icon-arrowthickstop-1-n'},
55 55 text : false
56 56 });
57 57 this.element.find('#insert_below_b').button({
58 58 icons: {primary: 'ui-icon-arrowthickstop-1-s'},
59 59 text : false
60 60 });
61 61 this.element.find('#insert_above_below').buttonset();
62 62 this.element.find('#run_b').button({
63 63 icons: {primary: 'ui-icon-play'},
64 64 text : false
65 65 });
66 66 this.element.find('#interrupt_b').button({
67 67 icons: {primary: 'ui-icon-stop'},
68 68 text : false
69 69 });
70 70 this.element.find('#run_int').buttonset();
71 71 };
72 72
73 73
74 74 ToolBar.prototype.bind_events = function () {
75 75 this.element.find('#save_b').click(function () {
76 76 IPython.save_widget.save_notebook();
77 77 });
78 78 this.element.find('#cut_b').click(function () {
79 79 IPython.notebook.cut_cell();
80 80 });
81 81 this.element.find('#copy_b').click(function () {
82 82 IPython.notebook.copy_cell();
83 83 });
84 84 this.element.find('#paste_b').click(function () {
85 85 IPython.notebook.paste_cell();
86 86 });
87 87 this.element.find('#move_up_b').click(function () {
88 88 IPython.notebook.move_cell_up();
89 89 });
90 90 this.element.find('#move_down_b').click(function () {
91 91 IPython.notebook.move_cell_down();
92 92 });
93 93 this.element.find('#insert_above_b').click(function () {
94 94 IPython.notebook.insert_cell_above('code');
95 95 });
96 96 this.element.find('#insert_below_b').click(function () {
97 97 IPython.notebook.insert_cell_below('code');
98 98 });
99 99 this.element.find('#run_b').click(function () {
100 100 IPython.notebook.execute_selected_cell();
101 101 });
102 102 this.element.find('#interrupt_b').click(function () {
103 103 IPython.notebook.kernel.interrupt();
104 104 });
105 105 this.element.find('#cell_type').change(function () {
106 106 var cell_type = $(this).val();
107 107 if (cell_type === 'code') {
108 108 IPython.notebook.to_code();
109 109 } else if (cell_type === 'markdown') {
110 110 IPython.notebook.to_markdown();
111 } else if (cell_type === 'plaintext') {
112 IPython.notebook.to_plaintext();
113 } else if (cell_type === 'heading1') {
114 IPython.notebook.to_heading(undefined, 1);
115 } else if (cell_type === 'heading2') {
116 IPython.notebook.to_heading(undefined, 2);
117 } else if (cell_type === 'heading3') {
118 IPython.notebook.to_heading(undefined, 3);
119 } else if (cell_type === 'heading4') {
120 IPython.notebook.to_heading(undefined, 4);
121 } else if (cell_type === 'heading5') {
122 IPython.notebook.to_heading(undefined, 5);
123 } else if (cell_type === 'heading6') {
124 IPython.notebook.to_heading(undefined, 6);
111 125 };
112 126 });
113 127
114 128 };
115 129
116 130
117 131 ToolBar.prototype.set_cell_type = function (cell_type) {
118 132 this.element.find('#cell_type').val(cell_type);
119 133 };
120 134
121 135
122 136 ToolBar.prototype.toggle = function () {
123 137 this.element.toggle();
124 138 IPython.layout_manager.do_resize();
125 139 };
126 140
127 141
128 142 IPython.ToolBar = ToolBar;
129 143
130 144 return IPython;
131 145
132 146 }(IPython));
@@ -1,234 +1,241 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 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 <option value="plaintext">Plaintext</option>
184 <option value="heading1">Heading 1</option>
185 <option value="heading2">Heading 2</option>
186 <option value="heading3">Heading 3</option>
187 <option value="heading4">Heading 4</option>
188 <option value="heading5">Heading 5</option>
189 <option value="heading6">Heading 6</option>
183 190 </select>
184 191 </span>
185 192
186 193 </div>
187 194
188 195 <div id="main_app">
189 196
190 197 <div id="notebook_panel">
191 198 <div id="notebook"></div>
192 199 <div id="pager_splitter"></div>
193 200 <div id="pager"></div>
194 201 </div>
195 202
196 203 </div>
197 204
198 205 <script src="{{ static_url("jquery/js/jquery-1.7.1.min.js") }}" type="text/javascript" charset="utf-8"></script>
199 206 <script src="{{ static_url("jquery/js/jquery-ui.min.js") }}" type="text/javascript" charset="utf-8"></script>
200 207
201 208 <script src="{{ static_url("codemirror/lib/codemirror.js") }}" charset="utf-8"></script>
202 209 <script src="{{ static_url("codemirror/mode/python/python.js") }}" charset="utf-8"></script>
203 210 <script src="{{ static_url("codemirror/mode/htmlmixed/htmlmixed.js") }}" charset="utf-8"></script>
204 211 <script src="{{ static_url("codemirror/mode/xml/xml.js") }}" charset="utf-8"></script>
205 212 <script src="{{ static_url("codemirror/mode/javascript/javascript.js") }}" charset="utf-8"></script>
206 213 <script src="{{ static_url("codemirror/mode/css/css.js") }}" charset="utf-8"></script>
207 214 <script src="{{ static_url("codemirror/mode/rst/rst.js") }}" charset="utf-8"></script>
208 215 <script src="{{ static_url("codemirror/mode/markdown/markdown.js") }}" charset="utf-8"></script>
209 216
210 217 <script src="{{ static_url("pagedown/Markdown.Converter.js") }}" charset="utf-8"></script>
211 218
212 219 <script src="{{ static_url("prettify/prettify.js") }}" charset="utf-8"></script>
213 220 <script src="{{ static_url("dateformat/date.format.js") }}" charset="utf-8"></script>
214 221
215 222 <script src="{{ static_url("js/namespace.js") }}" type="text/javascript" charset="utf-8"></script>
216 223 <script src="{{ static_url("js/utils.js") }}" type="text/javascript" charset="utf-8"></script>
217 224 <script src="{{ static_url("js/cell.js") }}" type="text/javascript" charset="utf-8"></script>
218 225 <script src="{{ static_url("js/codecell.js") }}" type="text/javascript" charset="utf-8"></script>
219 226 <script src="{{ static_url("js/textcell.js") }}" type="text/javascript" charset="utf-8"></script>
220 227 <script src="{{ static_url("js/kernel.js") }}" type="text/javascript" charset="utf-8"></script>
221 228 <script src="{{ static_url("js/kernelstatus.js") }}" type="text/javascript" charset="utf-8"></script>
222 229 <script src="{{ static_url("js/layout.js") }}" type="text/javascript" charset="utf-8"></script>
223 230 <script src="{{ static_url("js/savewidget.js") }}" type="text/javascript" charset="utf-8"></script>
224 231 <script src="{{ static_url("js/quickhelp.js") }}" type="text/javascript" charset="utf-8"></script>
225 232 <script src="{{ static_url("js/loginwidget.js") }}" type="text/javascript" charset="utf-8"></script>
226 233 <script src="{{ static_url("js/pager.js") }}" type="text/javascript" charset="utf-8"></script>
227 234 <script src="{{ static_url("js/menubar.js") }}" type="text/javascript" charset="utf-8"></script>
228 235 <script src="{{ static_url("js/toolbar.js") }}" type="text/javascript" charset="utf-8"></script>
229 236 <script src="{{ static_url("js/notebook.js") }}" type="text/javascript" charset="utf-8"></script>
230 237 <script src="{{ static_url("js/notebookmain.js") }}" type="text/javascript" charset="utf-8"></script>
231 238
232 239 </body>
233 240
234 241 </html>
General Comments 0
You need to be logged in to leave comments. Login now