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