##// END OF EJS Templates
Make 'Paste Above' the default paste behavior....
David Warde-Farley -
Show More
@@ -1,179 +1,179
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2011 The IPython Development Team
2 // Copyright (C) 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 // ToolBar
9 // ToolBar
10 //============================================================================
10 //============================================================================
11
11
12 var IPython = (function (IPython) {
12 var IPython = (function (IPython) {
13
13
14 var MainToolBar = function (selector) {
14 var MainToolBar = function (selector) {
15 this.selector = selector;
15 this.selector = selector;
16 IPython.ToolBar.apply(this, arguments);
16 IPython.ToolBar.apply(this, arguments);
17 this.construct();
17 this.construct();
18 this.add_drop_down_list();
18 this.add_drop_down_list();
19 this.bind_events();
19 this.bind_events();
20 };
20 };
21
21
22 MainToolBar.prototype = new IPython.ToolBar();
22 MainToolBar.prototype = new IPython.ToolBar();
23
23
24 MainToolBar.prototype.construct = function () {
24 MainToolBar.prototype.construct = function () {
25 this.add_buttons_group([
25 this.add_buttons_group([
26 {
26 {
27 id : 'save_b',
27 id : 'save_b',
28 label : 'Save',
28 label : 'Save',
29 icon : 'ui-icon-disk',
29 icon : 'ui-icon-disk',
30 callback : function () {
30 callback : function () {
31 IPython.notebook.save_notebook();
31 IPython.notebook.save_notebook();
32 }
32 }
33 }
33 }
34 ]);
34 ]);
35 this.add_buttons_group([
35 this.add_buttons_group([
36 {
36 {
37 id : 'cut_b',
37 id : 'cut_b',
38 label : 'Cut Cell',
38 label : 'Cut Cell',
39 icon : 'ui-icon-scissors',
39 icon : 'ui-icon-scissors',
40 callback : function () {
40 callback : function () {
41 IPython.notebook.cut_cell();
41 IPython.notebook.cut_cell();
42 }
42 }
43 },
43 },
44 {
44 {
45 id : 'copy_b',
45 id : 'copy_b',
46 label : 'Copy Cell',
46 label : 'Copy Cell',
47 icon : 'ui-icon-copy',
47 icon : 'ui-icon-copy',
48 callback : function () {
48 callback : function () {
49 IPython.notebook.copy_cell();
49 IPython.notebook.copy_cell();
50 }
50 }
51 },
51 },
52 {
52 {
53 id : 'paste_b',
53 id : 'paste_b',
54 label : 'Paste Cell',
54 label : 'Paste Cell Above',
55 icon : 'ui-icon-clipboard',
55 icon : 'ui-icon-clipboard',
56 callback : function () {
56 callback : function () {
57 IPython.notebook.paste_cell();
57 IPython.notebook.paste_cell_above();
58 }
58 }
59 }
59 }
60 ],'cut_copy_paste');
60 ],'cut_copy_paste');
61
61
62 this.add_buttons_group([
62 this.add_buttons_group([
63 {
63 {
64 id : 'move_up_b',
64 id : 'move_up_b',
65 label : 'Move Cell Up',
65 label : 'Move Cell Up',
66 icon : 'ui-icon-arrowthick-1-n',
66 icon : 'ui-icon-arrowthick-1-n',
67 callback : function () {
67 callback : function () {
68 IPython.notebook.move_cell_up();
68 IPython.notebook.move_cell_up();
69 }
69 }
70 },
70 },
71 {
71 {
72 id : 'move_down_b',
72 id : 'move_down_b',
73 label : 'Move Cell Down',
73 label : 'Move Cell Down',
74 icon : 'ui-icon-arrowthick-1-s',
74 icon : 'ui-icon-arrowthick-1-s',
75 callback : function () {
75 callback : function () {
76 IPython.notebook.move_cell_down();
76 IPython.notebook.move_cell_down();
77 }
77 }
78 }
78 }
79 ],'move_up_down');
79 ],'move_up_down');
80
80
81 this.add_buttons_group([
81 this.add_buttons_group([
82 {
82 {
83 id : 'insert_above_b',
83 id : 'insert_above_b',
84 label : 'Insert Cell Above',
84 label : 'Insert Cell Above',
85 icon : 'ui-icon-arrowthickstop-1-n',
85 icon : 'ui-icon-arrowthickstop-1-n',
86 callback : function () {
86 callback : function () {
87 IPython.notebook.insert_cell_above('code');
87 IPython.notebook.insert_cell_above('code');
88 }
88 }
89 },
89 },
90 {
90 {
91 id : 'insert_below_b',
91 id : 'insert_below_b',
92 label : 'Insert Cell Below',
92 label : 'Insert Cell Below',
93 icon : 'ui-icon-arrowthickstop-1-s',
93 icon : 'ui-icon-arrowthickstop-1-s',
94 callback : function () {
94 callback : function () {
95 IPython.notebook.insert_cell_below('code');
95 IPython.notebook.insert_cell_below('code');
96 }
96 }
97 }
97 }
98 ],'insert_above_below');
98 ],'insert_above_below');
99
99
100 this.add_buttons_group([
100 this.add_buttons_group([
101 {
101 {
102 id : 'run_b',
102 id : 'run_b',
103 label : 'Run Cell',
103 label : 'Run Cell',
104 icon : 'ui-icon-play',
104 icon : 'ui-icon-play',
105 callback : function () {
105 callback : function () {
106 IPython.notebook.execute_selected_cell();
106 IPython.notebook.execute_selected_cell();
107 }
107 }
108 },
108 },
109 {
109 {
110 id : 'interrupt_b',
110 id : 'interrupt_b',
111 label : 'Interrupt',
111 label : 'Interrupt',
112 icon : 'ui-icon-stop',
112 icon : 'ui-icon-stop',
113 callback : function () {
113 callback : function () {
114 IPython.notebook.kernel.interrupt();
114 IPython.notebook.kernel.interrupt();
115 }
115 }
116 }
116 }
117 ],'run_int');
117 ],'run_int');
118
118
119
119
120 };
120 };
121
121
122 MainToolBar.prototype.add_drop_down_list = function () {
122 MainToolBar.prototype.add_drop_down_list = function () {
123 var select = $(this.selector)
123 var select = $(this.selector)
124 .append($('<select/>')
124 .append($('<select/>')
125 .attr('id','cell_type')
125 .attr('id','cell_type')
126 .addClass('ui-widget ui-widget-content')
126 .addClass('ui-widget ui-widget-content')
127 .append($('<option/>').attr('value','code').text('Code'))
127 .append($('<option/>').attr('value','code').text('Code'))
128 .append($('<option/>').attr('value','markdown').text('Markdown'))
128 .append($('<option/>').attr('value','markdown').text('Markdown'))
129 .append($('<option/>').attr('value','raw').text('Raw Text'))
129 .append($('<option/>').attr('value','raw').text('Raw Text'))
130 .append($('<option/>').attr('value','heading1').text('Heading 1'))
130 .append($('<option/>').attr('value','heading1').text('Heading 1'))
131 .append($('<option/>').attr('value','heading2').text('Heading 2'))
131 .append($('<option/>').attr('value','heading2').text('Heading 2'))
132 .append($('<option/>').attr('value','heading3').text('Heading 3'))
132 .append($('<option/>').attr('value','heading3').text('Heading 3'))
133 .append($('<option/>').attr('value','heading4').text('Heading 4'))
133 .append($('<option/>').attr('value','heading4').text('Heading 4'))
134 .append($('<option/>').attr('value','heading5').text('Heading 5'))
134 .append($('<option/>').attr('value','heading5').text('Heading 5'))
135 .append($('<option/>').attr('value','heading6').text('Heading 6'))
135 .append($('<option/>').attr('value','heading6').text('Heading 6'))
136 .append($('<option/>').attr('value','heading7').text('Heading 7'))
136 .append($('<option/>').attr('value','heading7').text('Heading 7'))
137 .append($('<option/>').attr('value','heading8').text('Heading 8'))
137 .append($('<option/>').attr('value','heading8').text('Heading 8'))
138 );
138 );
139 };
139 };
140
140
141 MainToolBar.prototype.bind_events = function () {
141 MainToolBar.prototype.bind_events = function () {
142 var that = this;
142 var that = this;
143
143
144 this.element.find('#cell_type').change(function () {
144 this.element.find('#cell_type').change(function () {
145 var cell_type = $(this).val();
145 var cell_type = $(this).val();
146 if (cell_type === 'code') {
146 if (cell_type === 'code') {
147 IPython.notebook.to_code();
147 IPython.notebook.to_code();
148 } else if (cell_type === 'markdown') {
148 } else if (cell_type === 'markdown') {
149 IPython.notebook.to_markdown();
149 IPython.notebook.to_markdown();
150 } else if (cell_type === 'raw') {
150 } else if (cell_type === 'raw') {
151 IPython.notebook.to_raw();
151 IPython.notebook.to_raw();
152 } else if (cell_type === 'heading1') {
152 } else if (cell_type === 'heading1') {
153 IPython.notebook.to_heading(undefined, 1);
153 IPython.notebook.to_heading(undefined, 1);
154 } else if (cell_type === 'heading2') {
154 } else if (cell_type === 'heading2') {
155 IPython.notebook.to_heading(undefined, 2);
155 IPython.notebook.to_heading(undefined, 2);
156 } else if (cell_type === 'heading3') {
156 } else if (cell_type === 'heading3') {
157 IPython.notebook.to_heading(undefined, 3);
157 IPython.notebook.to_heading(undefined, 3);
158 } else if (cell_type === 'heading4') {
158 } else if (cell_type === 'heading4') {
159 IPython.notebook.to_heading(undefined, 4);
159 IPython.notebook.to_heading(undefined, 4);
160 } else if (cell_type === 'heading5') {
160 } else if (cell_type === 'heading5') {
161 IPython.notebook.to_heading(undefined, 5);
161 IPython.notebook.to_heading(undefined, 5);
162 } else if (cell_type === 'heading6') {
162 } else if (cell_type === 'heading6') {
163 IPython.notebook.to_heading(undefined, 6);
163 IPython.notebook.to_heading(undefined, 6);
164 }
164 }
165 });
165 });
166 $([IPython.events]).on('selected_cell_type_changed.Notebook', function (event, data) {
166 $([IPython.events]).on('selected_cell_type_changed.Notebook', function (event, data) {
167 if (data.cell_type === 'heading') {
167 if (data.cell_type === 'heading') {
168 that.element.find('#cell_type').val(data.cell_type+data.level);
168 that.element.find('#cell_type').val(data.cell_type+data.level);
169 } else {
169 } else {
170 that.element.find('#cell_type').val(data.cell_type);
170 that.element.find('#cell_type').val(data.cell_type);
171 }
171 }
172 });
172 });
173 };
173 };
174
174
175 IPython.MainToolBar = MainToolBar;
175 IPython.MainToolBar = MainToolBar;
176
176
177 return IPython;
177 return IPython;
178
178
179 }(IPython));
179 }(IPython));
@@ -1,1371 +1,1371
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 var key = IPython.utils.keycodes;
15 var key = IPython.utils.keycodes;
16
16
17 var Notebook = function (selector) {
17 var Notebook = function (selector) {
18 this.read_only = IPython.read_only;
18 this.read_only = IPython.read_only;
19 this.element = $(selector);
19 this.element = $(selector);
20 this.element.scroll();
20 this.element.scroll();
21 this.element.data("notebook", this);
21 this.element.data("notebook", this);
22 this.next_prompt_number = 1;
22 this.next_prompt_number = 1;
23 this.kernel = null;
23 this.kernel = null;
24 this.clipboard = null;
24 this.clipboard = null;
25 this.undelete_backup = null;
25 this.undelete_backup = null;
26 this.undelete_index = null;
26 this.undelete_index = null;
27 this.undelete_below = false;
27 this.undelete_below = false;
28 this.paste_enabled = false;
28 this.paste_enabled = false;
29 this.dirty = false;
29 this.dirty = false;
30 this.metadata = {};
30 this.metadata = {};
31 // single worksheet for now
31 // single worksheet for now
32 this.worksheet_metadata = {};
32 this.worksheet_metadata = {};
33 this.control_key_active = false;
33 this.control_key_active = false;
34 this.notebook_id = null;
34 this.notebook_id = null;
35 this.notebook_name = null;
35 this.notebook_name = null;
36 this.notebook_name_blacklist_re = /[\/\\:]/;
36 this.notebook_name_blacklist_re = /[\/\\:]/;
37 this.nbformat = 3 // Increment this when changing the nbformat
37 this.nbformat = 3 // Increment this when changing the nbformat
38 this.nbformat_minor = 0 // Increment this when changing the nbformat
38 this.nbformat_minor = 0 // Increment this when changing the nbformat
39 this.style();
39 this.style();
40 this.create_elements();
40 this.create_elements();
41 this.bind_events();
41 this.bind_events();
42 };
42 };
43
43
44
44
45 Notebook.prototype.style = function () {
45 Notebook.prototype.style = function () {
46 $('div#notebook').addClass('border-box-sizing');
46 $('div#notebook').addClass('border-box-sizing');
47 };
47 };
48
48
49
49
50 Notebook.prototype.create_elements = function () {
50 Notebook.prototype.create_elements = function () {
51 // We add this end_space div to the end of the notebook div to:
51 // We add this end_space div to the end of the notebook div to:
52 // i) provide a margin between the last cell and the end of the notebook
52 // i) provide a margin between the last cell and the end of the notebook
53 // ii) to prevent the div from scrolling up when the last cell is being
53 // ii) to prevent the div from scrolling up when the last cell is being
54 // edited, but is too low on the page, which browsers will do automatically.
54 // edited, but is too low on the page, which browsers will do automatically.
55 var that = this;
55 var that = this;
56 var end_space = $('<div/>').addClass('end_space').height("30%");
56 var end_space = $('<div/>').addClass('end_space').height("30%");
57 end_space.dblclick(function (e) {
57 end_space.dblclick(function (e) {
58 if (that.read_only) return;
58 if (that.read_only) return;
59 var ncells = that.ncells();
59 var ncells = that.ncells();
60 that.insert_cell_below('code',ncells-1);
60 that.insert_cell_below('code',ncells-1);
61 });
61 });
62 this.element.append(end_space);
62 this.element.append(end_space);
63 $('div#notebook').addClass('border-box-sizing');
63 $('div#notebook').addClass('border-box-sizing');
64 };
64 };
65
65
66
66
67 Notebook.prototype.bind_events = function () {
67 Notebook.prototype.bind_events = function () {
68 var that = this;
68 var that = this;
69
69
70 $([IPython.events]).on('set_next_input.Notebook', function (event, data) {
70 $([IPython.events]).on('set_next_input.Notebook', function (event, data) {
71 var index = that.find_cell_index(data.cell);
71 var index = that.find_cell_index(data.cell);
72 var new_cell = that.insert_cell_below('code',index);
72 var new_cell = that.insert_cell_below('code',index);
73 new_cell.set_text(data.text);
73 new_cell.set_text(data.text);
74 that.dirty = true;
74 that.dirty = true;
75 });
75 });
76
76
77 $([IPython.events]).on('set_dirty.Notebook', function (event, data) {
77 $([IPython.events]).on('set_dirty.Notebook', function (event, data) {
78 that.dirty = data.value;
78 that.dirty = data.value;
79 });
79 });
80
80
81 $([IPython.events]).on('select.Cell', function (event, data) {
81 $([IPython.events]).on('select.Cell', function (event, data) {
82 var index = that.find_cell_index(data.cell);
82 var index = that.find_cell_index(data.cell);
83 that.select(index);
83 that.select(index);
84 });
84 });
85
85
86
86
87 $(document).keydown(function (event) {
87 $(document).keydown(function (event) {
88 // console.log(event);
88 // console.log(event);
89 if (that.read_only) return true;
89 if (that.read_only) return true;
90
90
91 // Save (CTRL+S) or (AppleKey+S)
91 // Save (CTRL+S) or (AppleKey+S)
92 //metaKey = applekey on mac
92 //metaKey = applekey on mac
93 if ((event.ctrlKey || event.metaKey) && event.keyCode==83) {
93 if ((event.ctrlKey || event.metaKey) && event.keyCode==83) {
94 that.save_notebook();
94 that.save_notebook();
95 event.preventDefault();
95 event.preventDefault();
96 return false;
96 return false;
97 } else if (event.which === key.ESC) {
97 } else if (event.which === key.ESC) {
98 // Intercept escape at highest level to avoid closing
98 // Intercept escape at highest level to avoid closing
99 // websocket connection with firefox
99 // websocket connection with firefox
100 event.preventDefault();
100 event.preventDefault();
101 } else if (event.which === key.SHIFT) {
101 } else if (event.which === key.SHIFT) {
102 // ignore shift keydown
102 // ignore shift keydown
103 return true;
103 return true;
104 }
104 }
105 if (event.which === key.UPARROW && !event.shiftKey) {
105 if (event.which === key.UPARROW && !event.shiftKey) {
106 var cell = that.get_selected_cell();
106 var cell = that.get_selected_cell();
107 if (cell.at_top()) {
107 if (cell.at_top()) {
108 event.preventDefault();
108 event.preventDefault();
109 that.select_prev();
109 that.select_prev();
110 };
110 };
111 } else if (event.which === key.DOWNARROW && !event.shiftKey) {
111 } else if (event.which === key.DOWNARROW && !event.shiftKey) {
112 var cell = that.get_selected_cell();
112 var cell = that.get_selected_cell();
113 if (cell.at_bottom()) {
113 if (cell.at_bottom()) {
114 event.preventDefault();
114 event.preventDefault();
115 that.select_next();
115 that.select_next();
116 };
116 };
117 } else if (event.which === key.ENTER && event.shiftKey) {
117 } else if (event.which === key.ENTER && event.shiftKey) {
118 that.execute_selected_cell();
118 that.execute_selected_cell();
119 return false;
119 return false;
120 } else if (event.which === key.ENTER && event.altKey) {
120 } else if (event.which === key.ENTER && event.altKey) {
121 // Execute code cell, and insert new in place
121 // Execute code cell, and insert new in place
122 that.execute_selected_cell();
122 that.execute_selected_cell();
123 // Only insert a new cell, if we ended up in an already populated cell
123 // Only insert a new cell, if we ended up in an already populated cell
124 if (/\S/.test(that.get_selected_cell().get_text()) == true) {
124 if (/\S/.test(that.get_selected_cell().get_text()) == true) {
125 that.insert_cell_above('code');
125 that.insert_cell_above('code');
126 }
126 }
127 return false;
127 return false;
128 } else if (event.which === key.ENTER && event.ctrlKey) {
128 } else if (event.which === key.ENTER && event.ctrlKey) {
129 that.execute_selected_cell({terminal:true});
129 that.execute_selected_cell({terminal:true});
130 return false;
130 return false;
131 } else if (event.which === 77 && event.ctrlKey && that.control_key_active == false) {
131 } else if (event.which === 77 && event.ctrlKey && that.control_key_active == false) {
132 that.control_key_active = true;
132 that.control_key_active = true;
133 return false;
133 return false;
134 } else if (event.which === 88 && that.control_key_active) {
134 } else if (event.which === 88 && that.control_key_active) {
135 // Cut selected cell = x
135 // Cut selected cell = x
136 that.cut_cell();
136 that.cut_cell();
137 that.control_key_active = false;
137 that.control_key_active = false;
138 return false;
138 return false;
139 } else if (event.which === 67 && that.control_key_active) {
139 } else if (event.which === 67 && that.control_key_active) {
140 // Copy selected cell = c
140 // Copy selected cell = c
141 that.copy_cell();
141 that.copy_cell();
142 that.control_key_active = false;
142 that.control_key_active = false;
143 return false;
143 return false;
144 } else if (event.which === 86 && that.control_key_active) {
144 } else if (event.which === 86 && that.control_key_active) {
145 // Paste selected cell = v
145 // Paste above selected cell = v
146 that.paste_cell();
146 that.paste_cell_above();
147 that.control_key_active = false;
147 that.control_key_active = false;
148 return false;
148 return false;
149 } else if (event.which === 68 && that.control_key_active) {
149 } else if (event.which === 68 && that.control_key_active) {
150 // Delete selected cell = d
150 // Delete selected cell = d
151 that.delete_cell();
151 that.delete_cell();
152 that.control_key_active = false;
152 that.control_key_active = false;
153 return false;
153 return false;
154 } else if (event.which === 65 && that.control_key_active) {
154 } else if (event.which === 65 && that.control_key_active) {
155 // Insert code cell above selected = a
155 // Insert code cell above selected = a
156 that.insert_cell_above('code');
156 that.insert_cell_above('code');
157 that.control_key_active = false;
157 that.control_key_active = false;
158 return false;
158 return false;
159 } else if (event.which === 66 && that.control_key_active) {
159 } else if (event.which === 66 && that.control_key_active) {
160 // Insert code cell below selected = b
160 // Insert code cell below selected = b
161 that.insert_cell_below('code');
161 that.insert_cell_below('code');
162 that.control_key_active = false;
162 that.control_key_active = false;
163 return false;
163 return false;
164 } else if (event.which === 89 && that.control_key_active) {
164 } else if (event.which === 89 && that.control_key_active) {
165 // To code = y
165 // To code = y
166 that.to_code();
166 that.to_code();
167 that.control_key_active = false;
167 that.control_key_active = false;
168 return false;
168 return false;
169 } else if (event.which === 77 && that.control_key_active) {
169 } else if (event.which === 77 && that.control_key_active) {
170 // To markdown = m
170 // To markdown = m
171 that.to_markdown();
171 that.to_markdown();
172 that.control_key_active = false;
172 that.control_key_active = false;
173 return false;
173 return false;
174 } else if (event.which === 84 && that.control_key_active) {
174 } else if (event.which === 84 && that.control_key_active) {
175 // To Raw = t
175 // To Raw = t
176 that.to_raw();
176 that.to_raw();
177 that.control_key_active = false;
177 that.control_key_active = false;
178 return false;
178 return false;
179 } else if (event.which === 49 && that.control_key_active) {
179 } else if (event.which === 49 && that.control_key_active) {
180 // To Heading 1 = 1
180 // To Heading 1 = 1
181 that.to_heading(undefined, 1);
181 that.to_heading(undefined, 1);
182 that.control_key_active = false;
182 that.control_key_active = false;
183 return false;
183 return false;
184 } else if (event.which === 50 && that.control_key_active) {
184 } else if (event.which === 50 && that.control_key_active) {
185 // To Heading 2 = 2
185 // To Heading 2 = 2
186 that.to_heading(undefined, 2);
186 that.to_heading(undefined, 2);
187 that.control_key_active = false;
187 that.control_key_active = false;
188 return false;
188 return false;
189 } else if (event.which === 51 && that.control_key_active) {
189 } else if (event.which === 51 && that.control_key_active) {
190 // To Heading 3 = 3
190 // To Heading 3 = 3
191 that.to_heading(undefined, 3);
191 that.to_heading(undefined, 3);
192 that.control_key_active = false;
192 that.control_key_active = false;
193 return false;
193 return false;
194 } else if (event.which === 52 && that.control_key_active) {
194 } else if (event.which === 52 && that.control_key_active) {
195 // To Heading 4 = 4
195 // To Heading 4 = 4
196 that.to_heading(undefined, 4);
196 that.to_heading(undefined, 4);
197 that.control_key_active = false;
197 that.control_key_active = false;
198 return false;
198 return false;
199 } else if (event.which === 53 && that.control_key_active) {
199 } else if (event.which === 53 && that.control_key_active) {
200 // To Heading 5 = 5
200 // To Heading 5 = 5
201 that.to_heading(undefined, 5);
201 that.to_heading(undefined, 5);
202 that.control_key_active = false;
202 that.control_key_active = false;
203 return false;
203 return false;
204 } else if (event.which === 54 && that.control_key_active) {
204 } else if (event.which === 54 && that.control_key_active) {
205 // To Heading 6 = 6
205 // To Heading 6 = 6
206 that.to_heading(undefined, 6);
206 that.to_heading(undefined, 6);
207 that.control_key_active = false;
207 that.control_key_active = false;
208 return false;
208 return false;
209 } else if (event.which === 79 && that.control_key_active) {
209 } else if (event.which === 79 && that.control_key_active) {
210 // Toggle output = o
210 // Toggle output = o
211 if (event.shiftKey){
211 if (event.shiftKey){
212 that.toggle_output_scroll();
212 that.toggle_output_scroll();
213 } else {
213 } else {
214 that.toggle_output();
214 that.toggle_output();
215 }
215 }
216 that.control_key_active = false;
216 that.control_key_active = false;
217 return false;
217 return false;
218 } else if (event.which === 83 && that.control_key_active) {
218 } else if (event.which === 83 && that.control_key_active) {
219 // Save notebook = s
219 // Save notebook = s
220 that.save_notebook();
220 that.save_notebook();
221 that.control_key_active = false;
221 that.control_key_active = false;
222 return false;
222 return false;
223 } else if (event.which === 74 && that.control_key_active) {
223 } else if (event.which === 74 && that.control_key_active) {
224 // Move cell down = j
224 // Move cell down = j
225 that.move_cell_down();
225 that.move_cell_down();
226 that.control_key_active = false;
226 that.control_key_active = false;
227 return false;
227 return false;
228 } else if (event.which === 75 && that.control_key_active) {
228 } else if (event.which === 75 && that.control_key_active) {
229 // Move cell up = k
229 // Move cell up = k
230 that.move_cell_up();
230 that.move_cell_up();
231 that.control_key_active = false;
231 that.control_key_active = false;
232 return false;
232 return false;
233 } else if (event.which === 80 && that.control_key_active) {
233 } else if (event.which === 80 && that.control_key_active) {
234 // Select previous = p
234 // Select previous = p
235 that.select_prev();
235 that.select_prev();
236 that.control_key_active = false;
236 that.control_key_active = false;
237 return false;
237 return false;
238 } else if (event.which === 78 && that.control_key_active) {
238 } else if (event.which === 78 && that.control_key_active) {
239 // Select next = n
239 // Select next = n
240 that.select_next();
240 that.select_next();
241 that.control_key_active = false;
241 that.control_key_active = false;
242 return false;
242 return false;
243 } else if (event.which === 76 && that.control_key_active) {
243 } else if (event.which === 76 && that.control_key_active) {
244 // Toggle line numbers = l
244 // Toggle line numbers = l
245 that.cell_toggle_line_numbers();
245 that.cell_toggle_line_numbers();
246 that.control_key_active = false;
246 that.control_key_active = false;
247 return false;
247 return false;
248 } else if (event.which === 73 && that.control_key_active) {
248 } else if (event.which === 73 && that.control_key_active) {
249 // Interrupt kernel = i
249 // Interrupt kernel = i
250 that.kernel.interrupt();
250 that.kernel.interrupt();
251 that.control_key_active = false;
251 that.control_key_active = false;
252 return false;
252 return false;
253 } else if (event.which === 190 && that.control_key_active) {
253 } else if (event.which === 190 && that.control_key_active) {
254 // Restart kernel = . # matches qt console
254 // Restart kernel = . # matches qt console
255 that.restart_kernel();
255 that.restart_kernel();
256 that.control_key_active = false;
256 that.control_key_active = false;
257 return false;
257 return false;
258 } else if (event.which === 72 && that.control_key_active) {
258 } else if (event.which === 72 && that.control_key_active) {
259 // Show keyboard shortcuts = h
259 // Show keyboard shortcuts = h
260 IPython.quick_help.show_keyboard_shortcuts();
260 IPython.quick_help.show_keyboard_shortcuts();
261 that.control_key_active = false;
261 that.control_key_active = false;
262 return false;
262 return false;
263 } else if (event.which === 90 && that.control_key_active) {
263 } else if (event.which === 90 && that.control_key_active) {
264 // Undo last cell delete = z
264 // Undo last cell delete = z
265 that.undelete();
265 that.undelete();
266 that.control_key_active = false;
266 that.control_key_active = false;
267 return false;
267 return false;
268 } else if (that.control_key_active) {
268 } else if (that.control_key_active) {
269 that.control_key_active = false;
269 that.control_key_active = false;
270 return true;
270 return true;
271 };
271 };
272 return true;
272 return true;
273 });
273 });
274
274
275 var collapse_time = function(time){
275 var collapse_time = function(time){
276 var app_height = $('div#main_app').height(); // content height
276 var app_height = $('div#main_app').height(); // content height
277 var splitter_height = $('div#pager_splitter').outerHeight(true);
277 var splitter_height = $('div#pager_splitter').outerHeight(true);
278 var new_height = app_height - splitter_height;
278 var new_height = app_height - splitter_height;
279 that.element.animate({height : new_height + 'px'}, time);
279 that.element.animate({height : new_height + 'px'}, time);
280 }
280 }
281
281
282 this.element.bind('collapse_pager', function (event,extrap) {
282 this.element.bind('collapse_pager', function (event,extrap) {
283 time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast';
283 time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast';
284 collapse_time(time);
284 collapse_time(time);
285 });
285 });
286
286
287 var expand_time = function(time) {
287 var expand_time = function(time) {
288 var app_height = $('div#main_app').height(); // content height
288 var app_height = $('div#main_app').height(); // content height
289 var splitter_height = $('div#pager_splitter').outerHeight(true);
289 var splitter_height = $('div#pager_splitter').outerHeight(true);
290 var pager_height = $('div#pager').outerHeight(true);
290 var pager_height = $('div#pager').outerHeight(true);
291 var new_height = app_height - pager_height - splitter_height;
291 var new_height = app_height - pager_height - splitter_height;
292 that.element.animate({height : new_height + 'px'}, time);
292 that.element.animate({height : new_height + 'px'}, time);
293 }
293 }
294
294
295 this.element.bind('expand_pager', function (event, extrap) {
295 this.element.bind('expand_pager', function (event, extrap) {
296 time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast';
296 time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast';
297 expand_time(time);
297 expand_time(time);
298 });
298 });
299
299
300 $(window).bind('beforeunload', function () {
300 $(window).bind('beforeunload', function () {
301 // TODO: Make killing the kernel configurable.
301 // TODO: Make killing the kernel configurable.
302 var kill_kernel = false;
302 var kill_kernel = false;
303 if (kill_kernel) {
303 if (kill_kernel) {
304 that.kernel.kill();
304 that.kernel.kill();
305 }
305 }
306 if (that.dirty && ! that.read_only) {
306 if (that.dirty && ! that.read_only) {
307 return "You have unsaved changes that will be lost if you leave this page.";
307 return "You have unsaved changes that will be lost if you leave this page.";
308 };
308 };
309 // Null is the *only* return value that will make the browser not
309 // Null is the *only* return value that will make the browser not
310 // pop up the "don't leave" dialog.
310 // pop up the "don't leave" dialog.
311 return null;
311 return null;
312 });
312 });
313 };
313 };
314
314
315 Notebook.prototype.scroll_to_cell = function (cell_number, time) {
315 Notebook.prototype.scroll_to_cell = function (cell_number, time) {
316 var cells = this.get_cells();
316 var cells = this.get_cells();
317 var time = time || 0;
317 var time = time || 0;
318 cell_number = Math.min(cells.length-1,cell_number);
318 cell_number = Math.min(cells.length-1,cell_number);
319 cell_number = Math.max(0 ,cell_number);
319 cell_number = Math.max(0 ,cell_number);
320 scroll_value = cells[cell_number].element.position().top-cells[0].element.position().top ;
320 scroll_value = cells[cell_number].element.position().top-cells[0].element.position().top ;
321 this.element.animate({scrollTop:scroll_value}, time);
321 this.element.animate({scrollTop:scroll_value}, time);
322 return scroll_value;
322 return scroll_value;
323 };
323 };
324
324
325
325
326 Notebook.prototype.scroll_to_bottom = function () {
326 Notebook.prototype.scroll_to_bottom = function () {
327 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
327 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
328 };
328 };
329
329
330
330
331 Notebook.prototype.scroll_to_top = function () {
331 Notebook.prototype.scroll_to_top = function () {
332 this.element.animate({scrollTop:0}, 0);
332 this.element.animate({scrollTop:0}, 0);
333 };
333 };
334
334
335
335
336 // Cell indexing, retrieval, etc.
336 // Cell indexing, retrieval, etc.
337
337
338 Notebook.prototype.get_cell_elements = function () {
338 Notebook.prototype.get_cell_elements = function () {
339 return this.element.children("div.cell");
339 return this.element.children("div.cell");
340 };
340 };
341
341
342
342
343 Notebook.prototype.get_cell_element = function (index) {
343 Notebook.prototype.get_cell_element = function (index) {
344 var result = null;
344 var result = null;
345 var e = this.get_cell_elements().eq(index);
345 var e = this.get_cell_elements().eq(index);
346 if (e.length !== 0) {
346 if (e.length !== 0) {
347 result = e;
347 result = e;
348 }
348 }
349 return result;
349 return result;
350 };
350 };
351
351
352
352
353 Notebook.prototype.ncells = function (cell) {
353 Notebook.prototype.ncells = function (cell) {
354 return this.get_cell_elements().length;
354 return this.get_cell_elements().length;
355 };
355 };
356
356
357
357
358 // TODO: we are often calling cells as cells()[i], which we should optimize
358 // TODO: we are often calling cells as cells()[i], which we should optimize
359 // to cells(i) or a new method.
359 // to cells(i) or a new method.
360 Notebook.prototype.get_cells = function () {
360 Notebook.prototype.get_cells = function () {
361 return this.get_cell_elements().toArray().map(function (e) {
361 return this.get_cell_elements().toArray().map(function (e) {
362 return $(e).data("cell");
362 return $(e).data("cell");
363 });
363 });
364 };
364 };
365
365
366
366
367 Notebook.prototype.get_cell = function (index) {
367 Notebook.prototype.get_cell = function (index) {
368 var result = null;
368 var result = null;
369 var ce = this.get_cell_element(index);
369 var ce = this.get_cell_element(index);
370 if (ce !== null) {
370 if (ce !== null) {
371 result = ce.data('cell');
371 result = ce.data('cell');
372 }
372 }
373 return result;
373 return result;
374 }
374 }
375
375
376
376
377 Notebook.prototype.get_next_cell = function (cell) {
377 Notebook.prototype.get_next_cell = function (cell) {
378 var result = null;
378 var result = null;
379 var index = this.find_cell_index(cell);
379 var index = this.find_cell_index(cell);
380 if (index !== null && index < this.ncells()) {
380 if (index !== null && index < this.ncells()) {
381 result = this.get_cell(index+1);
381 result = this.get_cell(index+1);
382 }
382 }
383 return result;
383 return result;
384 }
384 }
385
385
386
386
387 Notebook.prototype.get_prev_cell = function (cell) {
387 Notebook.prototype.get_prev_cell = function (cell) {
388 var result = null;
388 var result = null;
389 var index = this.find_cell_index(cell);
389 var index = this.find_cell_index(cell);
390 if (index !== null && index > 1) {
390 if (index !== null && index > 1) {
391 result = this.get_cell(index-1);
391 result = this.get_cell(index-1);
392 }
392 }
393 return result;
393 return result;
394 }
394 }
395
395
396 Notebook.prototype.find_cell_index = function (cell) {
396 Notebook.prototype.find_cell_index = function (cell) {
397 var result = null;
397 var result = null;
398 this.get_cell_elements().filter(function (index) {
398 this.get_cell_elements().filter(function (index) {
399 if ($(this).data("cell") === cell) {
399 if ($(this).data("cell") === cell) {
400 result = index;
400 result = index;
401 };
401 };
402 });
402 });
403 return result;
403 return result;
404 };
404 };
405
405
406
406
407 Notebook.prototype.index_or_selected = function (index) {
407 Notebook.prototype.index_or_selected = function (index) {
408 var i;
408 var i;
409 if (index === undefined || index === null) {
409 if (index === undefined || index === null) {
410 i = this.get_selected_index();
410 i = this.get_selected_index();
411 if (i === null) {
411 if (i === null) {
412 i = 0;
412 i = 0;
413 }
413 }
414 } else {
414 } else {
415 i = index;
415 i = index;
416 }
416 }
417 return i;
417 return i;
418 };
418 };
419
419
420
420
421 Notebook.prototype.get_selected_cell = function () {
421 Notebook.prototype.get_selected_cell = function () {
422 var index = this.get_selected_index();
422 var index = this.get_selected_index();
423 return this.get_cell(index);
423 return this.get_cell(index);
424 };
424 };
425
425
426
426
427 Notebook.prototype.is_valid_cell_index = function (index) {
427 Notebook.prototype.is_valid_cell_index = function (index) {
428 if (index !== null && index >= 0 && index < this.ncells()) {
428 if (index !== null && index >= 0 && index < this.ncells()) {
429 return true;
429 return true;
430 } else {
430 } else {
431 return false;
431 return false;
432 };
432 };
433 }
433 }
434
434
435 Notebook.prototype.get_selected_index = function () {
435 Notebook.prototype.get_selected_index = function () {
436 var result = null;
436 var result = null;
437 this.get_cell_elements().filter(function (index) {
437 this.get_cell_elements().filter(function (index) {
438 if ($(this).data("cell").selected === true) {
438 if ($(this).data("cell").selected === true) {
439 result = index;
439 result = index;
440 };
440 };
441 });
441 });
442 return result;
442 return result;
443 };
443 };
444
444
445
445
446 // Cell selection.
446 // Cell selection.
447
447
448 Notebook.prototype.select = function (index) {
448 Notebook.prototype.select = function (index) {
449 if (index !== undefined && index >= 0 && index < this.ncells()) {
449 if (index !== undefined && index >= 0 && index < this.ncells()) {
450 sindex = this.get_selected_index()
450 sindex = this.get_selected_index()
451 if (sindex !== null && index !== sindex) {
451 if (sindex !== null && index !== sindex) {
452 this.get_cell(sindex).unselect();
452 this.get_cell(sindex).unselect();
453 };
453 };
454 var cell = this.get_cell(index)
454 var cell = this.get_cell(index)
455 cell.select();
455 cell.select();
456 if (cell.cell_type === 'heading') {
456 if (cell.cell_type === 'heading') {
457 $([IPython.events]).trigger('selected_cell_type_changed.Notebook',
457 $([IPython.events]).trigger('selected_cell_type_changed.Notebook',
458 {'cell_type':cell.cell_type,level:cell.level}
458 {'cell_type':cell.cell_type,level:cell.level}
459 );
459 );
460 } else {
460 } else {
461 $([IPython.events]).trigger('selected_cell_type_changed.Notebook',
461 $([IPython.events]).trigger('selected_cell_type_changed.Notebook',
462 {'cell_type':cell.cell_type}
462 {'cell_type':cell.cell_type}
463 );
463 );
464 };
464 };
465 };
465 };
466 return this;
466 return this;
467 };
467 };
468
468
469
469
470 Notebook.prototype.select_next = function () {
470 Notebook.prototype.select_next = function () {
471 var index = this.get_selected_index();
471 var index = this.get_selected_index();
472 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
472 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
473 this.select(index+1);
473 this.select(index+1);
474 };
474 };
475 return this;
475 return this;
476 };
476 };
477
477
478
478
479 Notebook.prototype.select_prev = function () {
479 Notebook.prototype.select_prev = function () {
480 var index = this.get_selected_index();
480 var index = this.get_selected_index();
481 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
481 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
482 this.select(index-1);
482 this.select(index-1);
483 };
483 };
484 return this;
484 return this;
485 };
485 };
486
486
487
487
488 // Cell movement
488 // Cell movement
489
489
490 Notebook.prototype.move_cell_up = function (index) {
490 Notebook.prototype.move_cell_up = function (index) {
491 var i = this.index_or_selected();
491 var i = this.index_or_selected();
492 if (i !== null && i < this.ncells() && i > 0) {
492 if (i !== null && i < this.ncells() && i > 0) {
493 var pivot = this.get_cell_element(i-1);
493 var pivot = this.get_cell_element(i-1);
494 var tomove = this.get_cell_element(i);
494 var tomove = this.get_cell_element(i);
495 if (pivot !== null && tomove !== null) {
495 if (pivot !== null && tomove !== null) {
496 tomove.detach();
496 tomove.detach();
497 pivot.before(tomove);
497 pivot.before(tomove);
498 this.select(i-1);
498 this.select(i-1);
499 };
499 };
500 };
500 };
501 this.dirty = true;
501 this.dirty = true;
502 return this;
502 return this;
503 };
503 };
504
504
505
505
506 Notebook.prototype.move_cell_down = function (index) {
506 Notebook.prototype.move_cell_down = function (index) {
507 var i = this.index_or_selected();
507 var i = this.index_or_selected();
508 if (i !== null && i < (this.ncells()-1) && i >= 0) {
508 if (i !== null && i < (this.ncells()-1) && i >= 0) {
509 var pivot = this.get_cell_element(i+1);
509 var pivot = this.get_cell_element(i+1);
510 var tomove = this.get_cell_element(i);
510 var tomove = this.get_cell_element(i);
511 if (pivot !== null && tomove !== null) {
511 if (pivot !== null && tomove !== null) {
512 tomove.detach();
512 tomove.detach();
513 pivot.after(tomove);
513 pivot.after(tomove);
514 this.select(i+1);
514 this.select(i+1);
515 };
515 };
516 };
516 };
517 this.dirty = true;
517 this.dirty = true;
518 return this;
518 return this;
519 };
519 };
520
520
521
521
522 Notebook.prototype.sort_cells = function () {
522 Notebook.prototype.sort_cells = function () {
523 // This is not working right now. Calling this will actually crash
523 // This is not working right now. Calling this will actually crash
524 // the browser. I think there is an infinite loop in here...
524 // the browser. I think there is an infinite loop in here...
525 var ncells = this.ncells();
525 var ncells = this.ncells();
526 var sindex = this.get_selected_index();
526 var sindex = this.get_selected_index();
527 var swapped;
527 var swapped;
528 do {
528 do {
529 swapped = false;
529 swapped = false;
530 for (var i=1; i<ncells; i++) {
530 for (var i=1; i<ncells; i++) {
531 current = this.get_cell(i);
531 current = this.get_cell(i);
532 previous = this.get_cell(i-1);
532 previous = this.get_cell(i-1);
533 if (previous.input_prompt_number > current.input_prompt_number) {
533 if (previous.input_prompt_number > current.input_prompt_number) {
534 this.move_cell_up(i);
534 this.move_cell_up(i);
535 swapped = true;
535 swapped = true;
536 };
536 };
537 };
537 };
538 } while (swapped);
538 } while (swapped);
539 this.select(sindex);
539 this.select(sindex);
540 return this;
540 return this;
541 };
541 };
542
542
543 // Insertion, deletion.
543 // Insertion, deletion.
544
544
545 Notebook.prototype.delete_cell = function (index) {
545 Notebook.prototype.delete_cell = function (index) {
546 var i = this.index_or_selected(index);
546 var i = this.index_or_selected(index);
547 var cell = this.get_selected_cell();
547 var cell = this.get_selected_cell();
548 this.undelete_backup = cell.toJSON();
548 this.undelete_backup = cell.toJSON();
549 if (this.is_valid_cell_index(i)) {
549 if (this.is_valid_cell_index(i)) {
550 var ce = this.get_cell_element(i);
550 var ce = this.get_cell_element(i);
551 ce.remove();
551 ce.remove();
552 if (i === (this.ncells())) {
552 if (i === (this.ncells())) {
553 this.select(i-1);
553 this.select(i-1);
554 this.undelete_index = i - 1;
554 this.undelete_index = i - 1;
555 this.undelete_below = true;
555 this.undelete_below = true;
556 } else {
556 } else {
557 this.select(i);
557 this.select(i);
558 this.undelete_index = i;
558 this.undelete_index = i;
559 this.undelete_below = false;
559 this.undelete_below = false;
560 };
560 };
561 this.dirty = true;
561 this.dirty = true;
562 };
562 };
563 return this;
563 return this;
564 };
564 };
565
565
566
566
567 Notebook.prototype.insert_cell_at_bottom = function (type){
567 Notebook.prototype.insert_cell_at_bottom = function (type){
568 var len = this.ncells();
568 var len = this.ncells();
569 return this.insert_cell_below(type,len-1);
569 return this.insert_cell_below(type,len-1);
570 }
570 }
571
571
572 Notebook.prototype.insert_cell_below = function (type, index) {
572 Notebook.prototype.insert_cell_below = function (type, index) {
573 // type = ('code','html','markdown')
573 // type = ('code','html','markdown')
574 // index = cell index or undefined to insert below selected
574 // index = cell index or undefined to insert below selected
575 index = this.index_or_selected(index);
575 index = this.index_or_selected(index);
576 var cell = null;
576 var cell = null;
577 // This is intentionally < rather than <= for the sake of more
577 // This is intentionally < rather than <= for the sake of more
578 // sensible behavior in some cases.
578 // sensible behavior in some cases.
579 if (this.undelete_index !== null && index < this.undelete_index) {
579 if (this.undelete_index !== null && index < this.undelete_index) {
580 this.undelete_index = this.undelete_index + 1;
580 this.undelete_index = this.undelete_index + 1;
581 }
581 }
582 if (this.ncells() === 0 || this.is_valid_cell_index(index)) {
582 if (this.ncells() === 0 || this.is_valid_cell_index(index)) {
583 if (type === 'code') {
583 if (type === 'code') {
584 cell = new IPython.CodeCell(this.kernel);
584 cell = new IPython.CodeCell(this.kernel);
585 cell.set_input_prompt();
585 cell.set_input_prompt();
586 } else if (type === 'markdown') {
586 } else if (type === 'markdown') {
587 cell = new IPython.MarkdownCell();
587 cell = new IPython.MarkdownCell();
588 } else if (type === 'html') {
588 } else if (type === 'html') {
589 cell = new IPython.HTMLCell();
589 cell = new IPython.HTMLCell();
590 } else if (type === 'raw') {
590 } else if (type === 'raw') {
591 cell = new IPython.RawCell();
591 cell = new IPython.RawCell();
592 } else if (type === 'heading') {
592 } else if (type === 'heading') {
593 cell = new IPython.HeadingCell();
593 cell = new IPython.HeadingCell();
594 };
594 };
595 if (cell !== null) {
595 if (cell !== null) {
596 if (this.ncells() === 0) {
596 if (this.ncells() === 0) {
597 this.element.find('div.end_space').before(cell.element);
597 this.element.find('div.end_space').before(cell.element);
598 } else if (this.is_valid_cell_index(index)) {
598 } else if (this.is_valid_cell_index(index)) {
599 this.get_cell_element(index).after(cell.element);
599 this.get_cell_element(index).after(cell.element);
600 };
600 };
601 cell.render();
601 cell.render();
602 this.select(this.find_cell_index(cell));
602 this.select(this.find_cell_index(cell));
603 this.dirty = true;
603 this.dirty = true;
604 return cell;
604 return cell;
605 };
605 };
606 };
606 };
607 return cell;
607 return cell;
608 };
608 };
609
609
610
610
611 Notebook.prototype.insert_cell_above = function (type, index) {
611 Notebook.prototype.insert_cell_above = function (type, index) {
612 // type = ('code','html','markdown')
612 // type = ('code','html','markdown')
613 // index = cell index or undefined to insert above selected
613 // index = cell index or undefined to insert above selected
614 index = this.index_or_selected(index);
614 index = this.index_or_selected(index);
615 var cell = null;
615 var cell = null;
616 if (this.undelete_index !== null && index <= this.undelete_index) {
616 if (this.undelete_index !== null && index <= this.undelete_index) {
617 this.undelete_index = this.undelete_index + 1;
617 this.undelete_index = this.undelete_index + 1;
618 }
618 }
619 if (this.ncells() === 0 || this.is_valid_cell_index(index)) {
619 if (this.ncells() === 0 || this.is_valid_cell_index(index)) {
620 if (type === 'code') {
620 if (type === 'code') {
621 cell = new IPython.CodeCell(this.kernel);
621 cell = new IPython.CodeCell(this.kernel);
622 cell.set_input_prompt();
622 cell.set_input_prompt();
623 } else if (type === 'markdown') {
623 } else if (type === 'markdown') {
624 cell = new IPython.MarkdownCell();
624 cell = new IPython.MarkdownCell();
625 } else if (type === 'html') {
625 } else if (type === 'html') {
626 cell = new IPython.HTMLCell();
626 cell = new IPython.HTMLCell();
627 } else if (type === 'raw') {
627 } else if (type === 'raw') {
628 cell = new IPython.RawCell();
628 cell = new IPython.RawCell();
629 } else if (type === 'heading') {
629 } else if (type === 'heading') {
630 cell = new IPython.HeadingCell();
630 cell = new IPython.HeadingCell();
631 };
631 };
632 if (cell !== null) {
632 if (cell !== null) {
633 if (this.ncells() === 0) {
633 if (this.ncells() === 0) {
634 this.element.find('div.end_space').before(cell.element);
634 this.element.find('div.end_space').before(cell.element);
635 } else if (this.is_valid_cell_index(index)) {
635 } else if (this.is_valid_cell_index(index)) {
636 this.get_cell_element(index).before(cell.element);
636 this.get_cell_element(index).before(cell.element);
637 };
637 };
638 cell.render();
638 cell.render();
639 this.select(this.find_cell_index(cell));
639 this.select(this.find_cell_index(cell));
640 this.dirty = true;
640 this.dirty = true;
641 return cell;
641 return cell;
642 };
642 };
643 };
643 };
644 return cell;
644 return cell;
645 };
645 };
646
646
647
647
648 Notebook.prototype.to_code = function (index) {
648 Notebook.prototype.to_code = function (index) {
649 var i = this.index_or_selected(index);
649 var i = this.index_or_selected(index);
650 if (this.is_valid_cell_index(i)) {
650 if (this.is_valid_cell_index(i)) {
651 var source_element = this.get_cell_element(i);
651 var source_element = this.get_cell_element(i);
652 var source_cell = source_element.data("cell");
652 var source_cell = source_element.data("cell");
653 if (!(source_cell instanceof IPython.CodeCell)) {
653 if (!(source_cell instanceof IPython.CodeCell)) {
654 target_cell = this.insert_cell_below('code',i);
654 target_cell = this.insert_cell_below('code',i);
655 var text = source_cell.get_text();
655 var text = source_cell.get_text();
656 if (text === source_cell.placeholder) {
656 if (text === source_cell.placeholder) {
657 text = '';
657 text = '';
658 }
658 }
659 target_cell.set_text(text);
659 target_cell.set_text(text);
660 // make this value the starting point, so that we can only undo
660 // make this value the starting point, so that we can only undo
661 // to this state, instead of a blank cell
661 // to this state, instead of a blank cell
662 target_cell.code_mirror.clearHistory();
662 target_cell.code_mirror.clearHistory();
663 source_element.remove();
663 source_element.remove();
664 this.dirty = true;
664 this.dirty = true;
665 };
665 };
666 };
666 };
667 };
667 };
668
668
669
669
670 Notebook.prototype.to_markdown = function (index) {
670 Notebook.prototype.to_markdown = function (index) {
671 var i = this.index_or_selected(index);
671 var i = this.index_or_selected(index);
672 if (this.is_valid_cell_index(i)) {
672 if (this.is_valid_cell_index(i)) {
673 var source_element = this.get_cell_element(i);
673 var source_element = this.get_cell_element(i);
674 var source_cell = source_element.data("cell");
674 var source_cell = source_element.data("cell");
675 if (!(source_cell instanceof IPython.MarkdownCell)) {
675 if (!(source_cell instanceof IPython.MarkdownCell)) {
676 target_cell = this.insert_cell_below('markdown',i);
676 target_cell = this.insert_cell_below('markdown',i);
677 var text = source_cell.get_text();
677 var text = source_cell.get_text();
678 if (text === source_cell.placeholder) {
678 if (text === source_cell.placeholder) {
679 text = '';
679 text = '';
680 };
680 };
681 // The edit must come before the set_text.
681 // The edit must come before the set_text.
682 target_cell.edit();
682 target_cell.edit();
683 target_cell.set_text(text);
683 target_cell.set_text(text);
684 // make this value the starting point, so that we can only undo
684 // make this value the starting point, so that we can only undo
685 // to this state, instead of a blank cell
685 // to this state, instead of a blank cell
686 target_cell.code_mirror.clearHistory();
686 target_cell.code_mirror.clearHistory();
687 source_element.remove();
687 source_element.remove();
688 this.dirty = true;
688 this.dirty = true;
689 };
689 };
690 };
690 };
691 };
691 };
692
692
693
693
694 Notebook.prototype.to_html = function (index) {
694 Notebook.prototype.to_html = function (index) {
695 var i = this.index_or_selected(index);
695 var i = this.index_or_selected(index);
696 if (this.is_valid_cell_index(i)) {
696 if (this.is_valid_cell_index(i)) {
697 var source_element = this.get_cell_element(i);
697 var source_element = this.get_cell_element(i);
698 var source_cell = source_element.data("cell");
698 var source_cell = source_element.data("cell");
699 var target_cell = null;
699 var target_cell = null;
700 if (!(source_cell instanceof IPython.HTMLCell)) {
700 if (!(source_cell instanceof IPython.HTMLCell)) {
701 target_cell = this.insert_cell_below('html',i);
701 target_cell = this.insert_cell_below('html',i);
702 var text = source_cell.get_text();
702 var text = source_cell.get_text();
703 if (text === source_cell.placeholder) {
703 if (text === source_cell.placeholder) {
704 text = '';
704 text = '';
705 };
705 };
706 // The edit must come before the set_text.
706 // The edit must come before the set_text.
707 target_cell.edit();
707 target_cell.edit();
708 target_cell.set_text(text);
708 target_cell.set_text(text);
709 // make this value the starting point, so that we can only undo
709 // make this value the starting point, so that we can only undo
710 // to this state, instead of a blank cell
710 // to this state, instead of a blank cell
711 target_cell.code_mirror.clearHistory();
711 target_cell.code_mirror.clearHistory();
712 source_element.remove();
712 source_element.remove();
713 this.dirty = true;
713 this.dirty = true;
714 };
714 };
715 };
715 };
716 };
716 };
717
717
718
718
719 Notebook.prototype.to_raw = function (index) {
719 Notebook.prototype.to_raw = function (index) {
720 var i = this.index_or_selected(index);
720 var i = this.index_or_selected(index);
721 if (this.is_valid_cell_index(i)) {
721 if (this.is_valid_cell_index(i)) {
722 var source_element = this.get_cell_element(i);
722 var source_element = this.get_cell_element(i);
723 var source_cell = source_element.data("cell");
723 var source_cell = source_element.data("cell");
724 var target_cell = null;
724 var target_cell = null;
725 if (!(source_cell instanceof IPython.RawCell)) {
725 if (!(source_cell instanceof IPython.RawCell)) {
726 target_cell = this.insert_cell_below('raw',i);
726 target_cell = this.insert_cell_below('raw',i);
727 var text = source_cell.get_text();
727 var text = source_cell.get_text();
728 if (text === source_cell.placeholder) {
728 if (text === source_cell.placeholder) {
729 text = '';
729 text = '';
730 };
730 };
731 // The edit must come before the set_text.
731 // The edit must come before the set_text.
732 target_cell.edit();
732 target_cell.edit();
733 target_cell.set_text(text);
733 target_cell.set_text(text);
734 // make this value the starting point, so that we can only undo
734 // make this value the starting point, so that we can only undo
735 // to this state, instead of a blank cell
735 // to this state, instead of a blank cell
736 target_cell.code_mirror.clearHistory();
736 target_cell.code_mirror.clearHistory();
737 source_element.remove();
737 source_element.remove();
738 this.dirty = true;
738 this.dirty = true;
739 };
739 };
740 };
740 };
741 };
741 };
742
742
743
743
744 Notebook.prototype.to_heading = function (index, level) {
744 Notebook.prototype.to_heading = function (index, level) {
745 level = level || 1;
745 level = level || 1;
746 var i = this.index_or_selected(index);
746 var i = this.index_or_selected(index);
747 if (this.is_valid_cell_index(i)) {
747 if (this.is_valid_cell_index(i)) {
748 var source_element = this.get_cell_element(i);
748 var source_element = this.get_cell_element(i);
749 var source_cell = source_element.data("cell");
749 var source_cell = source_element.data("cell");
750 var target_cell = null;
750 var target_cell = null;
751 if (source_cell instanceof IPython.HeadingCell) {
751 if (source_cell instanceof IPython.HeadingCell) {
752 source_cell.set_level(level);
752 source_cell.set_level(level);
753 } else {
753 } else {
754 target_cell = this.insert_cell_below('heading',i);
754 target_cell = this.insert_cell_below('heading',i);
755 var text = source_cell.get_text();
755 var text = source_cell.get_text();
756 if (text === source_cell.placeholder) {
756 if (text === source_cell.placeholder) {
757 text = '';
757 text = '';
758 };
758 };
759 // The edit must come before the set_text.
759 // The edit must come before the set_text.
760 target_cell.set_level(level);
760 target_cell.set_level(level);
761 target_cell.edit();
761 target_cell.edit();
762 target_cell.set_text(text);
762 target_cell.set_text(text);
763 // make this value the starting point, so that we can only undo
763 // make this value the starting point, so that we can only undo
764 // to this state, instead of a blank cell
764 // to this state, instead of a blank cell
765 target_cell.code_mirror.clearHistory();
765 target_cell.code_mirror.clearHistory();
766 source_element.remove();
766 source_element.remove();
767 this.dirty = true;
767 this.dirty = true;
768 };
768 };
769 $([IPython.events]).trigger('selected_cell_type_changed.Notebook',
769 $([IPython.events]).trigger('selected_cell_type_changed.Notebook',
770 {'cell_type':'heading',level:level}
770 {'cell_type':'heading',level:level}
771 );
771 );
772 };
772 };
773 };
773 };
774
774
775
775
776 // Cut/Copy/Paste
776 // Cut/Copy/Paste
777
777
778 Notebook.prototype.enable_paste = function () {
778 Notebook.prototype.enable_paste = function () {
779 var that = this;
779 var that = this;
780 if (!this.paste_enabled) {
780 if (!this.paste_enabled) {
781 $('#paste_cell').removeClass('ui-state-disabled')
781 $('#paste_cell_replace').removeClass('ui-state-disabled')
782 .on('click', function () {that.paste_cell();});
782 .on('click', function () {that.paste_cell_replace();});
783 $('#paste_cell_above').removeClass('ui-state-disabled')
783 $('#paste_cell_above').removeClass('ui-state-disabled')
784 .on('click', function () {that.paste_cell_above();});
784 .on('click', function () {that.paste_cell_above();});
785 $('#paste_cell_below').removeClass('ui-state-disabled')
785 $('#paste_cell_below').removeClass('ui-state-disabled')
786 .on('click', function () {that.paste_cell_below();});
786 .on('click', function () {that.paste_cell_below();});
787 this.paste_enabled = true;
787 this.paste_enabled = true;
788 };
788 };
789 };
789 };
790
790
791
791
792 Notebook.prototype.disable_paste = function () {
792 Notebook.prototype.disable_paste = function () {
793 if (this.paste_enabled) {
793 if (this.paste_enabled) {
794 $('#paste_cell').addClass('ui-state-disabled').off('click');
794 $('#paste_cell_replace').addClass('ui-state-disabled').off('click');
795 $('#paste_cell_above').addClass('ui-state-disabled').off('click');
795 $('#paste_cell_above').addClass('ui-state-disabled').off('click');
796 $('#paste_cell_below').addClass('ui-state-disabled').off('click');
796 $('#paste_cell_below').addClass('ui-state-disabled').off('click');
797 this.paste_enabled = false;
797 this.paste_enabled = false;
798 };
798 };
799 };
799 };
800
800
801
801
802 Notebook.prototype.cut_cell = function () {
802 Notebook.prototype.cut_cell = function () {
803 this.copy_cell();
803 this.copy_cell();
804 this.delete_cell();
804 this.delete_cell();
805 }
805 }
806
806
807 Notebook.prototype.copy_cell = function () {
807 Notebook.prototype.copy_cell = function () {
808 var cell = this.get_selected_cell();
808 var cell = this.get_selected_cell();
809 this.clipboard = cell.toJSON();
809 this.clipboard = cell.toJSON();
810 this.enable_paste();
810 this.enable_paste();
811 };
811 };
812
812
813
813
814 Notebook.prototype.paste_cell = function () {
814 Notebook.prototype.paste_cell_replace = function () {
815 if (this.clipboard !== null && this.paste_enabled) {
815 if (this.clipboard !== null && this.paste_enabled) {
816 var cell_data = this.clipboard;
816 var cell_data = this.clipboard;
817 var new_cell = this.insert_cell_above(cell_data.cell_type);
817 var new_cell = this.insert_cell_above(cell_data.cell_type);
818 new_cell.fromJSON(cell_data);
818 new_cell.fromJSON(cell_data);
819 old_cell = this.get_next_cell(new_cell);
819 old_cell = this.get_next_cell(new_cell);
820 this.delete_cell(this.find_cell_index(old_cell));
820 this.delete_cell(this.find_cell_index(old_cell));
821 this.select(this.find_cell_index(new_cell));
821 this.select(this.find_cell_index(new_cell));
822 };
822 };
823 };
823 };
824
824
825
825
826 Notebook.prototype.paste_cell_above = function () {
826 Notebook.prototype.paste_cell_above = function () {
827 if (this.clipboard !== null && this.paste_enabled) {
827 if (this.clipboard !== null && this.paste_enabled) {
828 var cell_data = this.clipboard;
828 var cell_data = this.clipboard;
829 var new_cell = this.insert_cell_above(cell_data.cell_type);
829 var new_cell = this.insert_cell_above(cell_data.cell_type);
830 new_cell.fromJSON(cell_data);
830 new_cell.fromJSON(cell_data);
831 };
831 };
832 };
832 };
833
833
834
834
835 Notebook.prototype.paste_cell_below = function () {
835 Notebook.prototype.paste_cell_below = function () {
836 if (this.clipboard !== null && this.paste_enabled) {
836 if (this.clipboard !== null && this.paste_enabled) {
837 var cell_data = this.clipboard;
837 var cell_data = this.clipboard;
838 var new_cell = this.insert_cell_below(cell_data.cell_type);
838 var new_cell = this.insert_cell_below(cell_data.cell_type);
839 new_cell.fromJSON(cell_data);
839 new_cell.fromJSON(cell_data);
840 };
840 };
841 };
841 };
842
842
843 // Cell undelete
843 // Cell undelete
844
844
845 Notebook.prototype.undelete = function() {
845 Notebook.prototype.undelete = function() {
846 if (this.undelete_backup !== null && this.undelete_index !== null) {
846 if (this.undelete_backup !== null && this.undelete_index !== null) {
847 var current_index = this.get_selected_index();
847 var current_index = this.get_selected_index();
848 if (this.undelete_index < current_index) {
848 if (this.undelete_index < current_index) {
849 current_index = current_index + 1;
849 current_index = current_index + 1;
850 }
850 }
851 if (this.undelete_index >= this.ncells()) {
851 if (this.undelete_index >= this.ncells()) {
852 this.select(this.ncells() - 1);
852 this.select(this.ncells() - 1);
853 }
853 }
854 else {
854 else {
855 this.select(this.undelete_index);
855 this.select(this.undelete_index);
856 }
856 }
857 var cell_data = this.undelete_backup;
857 var cell_data = this.undelete_backup;
858 var new_cell = null;
858 var new_cell = null;
859 if (this.undelete_below) {
859 if (this.undelete_below) {
860 new_cell = this.insert_cell_below(cell_data.cell_type);
860 new_cell = this.insert_cell_below(cell_data.cell_type);
861 } else {
861 } else {
862 new_cell = this.insert_cell_above(cell_data.cell_type);
862 new_cell = this.insert_cell_above(cell_data.cell_type);
863 }
863 }
864 new_cell.fromJSON(cell_data);
864 new_cell.fromJSON(cell_data);
865 this.select(current_index);
865 this.select(current_index);
866 this.undelete_backup = null;
866 this.undelete_backup = null;
867 this.undelete_index = null;
867 this.undelete_index = null;
868 }
868 }
869 }
869 }
870
870
871 // Split/merge
871 // Split/merge
872
872
873 Notebook.prototype.split_cell = function () {
873 Notebook.prototype.split_cell = function () {
874 // Todo: implement spliting for other cell types.
874 // Todo: implement spliting for other cell types.
875 var cell = this.get_selected_cell();
875 var cell = this.get_selected_cell();
876 if (cell.is_splittable()) {
876 if (cell.is_splittable()) {
877 texta = cell.get_pre_cursor();
877 texta = cell.get_pre_cursor();
878 textb = cell.get_post_cursor();
878 textb = cell.get_post_cursor();
879 if (cell instanceof IPython.CodeCell) {
879 if (cell instanceof IPython.CodeCell) {
880 cell.set_text(texta);
880 cell.set_text(texta);
881 var new_cell = this.insert_cell_below('code');
881 var new_cell = this.insert_cell_below('code');
882 new_cell.set_text(textb);
882 new_cell.set_text(textb);
883 } else if (cell instanceof IPython.MarkdownCell) {
883 } else if (cell instanceof IPython.MarkdownCell) {
884 cell.set_text(texta);
884 cell.set_text(texta);
885 cell.render();
885 cell.render();
886 var new_cell = this.insert_cell_below('markdown');
886 var new_cell = this.insert_cell_below('markdown');
887 new_cell.edit(); // editor must be visible to call set_text
887 new_cell.edit(); // editor must be visible to call set_text
888 new_cell.set_text(textb);
888 new_cell.set_text(textb);
889 new_cell.render();
889 new_cell.render();
890 } else if (cell instanceof IPython.HTMLCell) {
890 } else if (cell instanceof IPython.HTMLCell) {
891 cell.set_text(texta);
891 cell.set_text(texta);
892 cell.render();
892 cell.render();
893 var new_cell = this.insert_cell_below('html');
893 var new_cell = this.insert_cell_below('html');
894 new_cell.edit(); // editor must be visible to call set_text
894 new_cell.edit(); // editor must be visible to call set_text
895 new_cell.set_text(textb);
895 new_cell.set_text(textb);
896 new_cell.render();
896 new_cell.render();
897 };
897 };
898 };
898 };
899 };
899 };
900
900
901
901
902 Notebook.prototype.merge_cell_above = function () {
902 Notebook.prototype.merge_cell_above = function () {
903 var index = this.get_selected_index();
903 var index = this.get_selected_index();
904 var cell = this.get_cell(index);
904 var cell = this.get_cell(index);
905 if (index > 0) {
905 if (index > 0) {
906 upper_cell = this.get_cell(index-1);
906 upper_cell = this.get_cell(index-1);
907 upper_text = upper_cell.get_text();
907 upper_text = upper_cell.get_text();
908 text = cell.get_text();
908 text = cell.get_text();
909 if (cell instanceof IPython.CodeCell) {
909 if (cell instanceof IPython.CodeCell) {
910 cell.set_text(upper_text+'\n'+text);
910 cell.set_text(upper_text+'\n'+text);
911 } else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) {
911 } else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) {
912 cell.edit();
912 cell.edit();
913 cell.set_text(upper_text+'\n'+text);
913 cell.set_text(upper_text+'\n'+text);
914 cell.render();
914 cell.render();
915 };
915 };
916 this.delete_cell(index-1);
916 this.delete_cell(index-1);
917 this.select(this.find_cell_index(cell));
917 this.select(this.find_cell_index(cell));
918 };
918 };
919 };
919 };
920
920
921
921
922 Notebook.prototype.merge_cell_below = function () {
922 Notebook.prototype.merge_cell_below = function () {
923 var index = this.get_selected_index();
923 var index = this.get_selected_index();
924 var cell = this.get_cell(index);
924 var cell = this.get_cell(index);
925 if (index < this.ncells()-1) {
925 if (index < this.ncells()-1) {
926 lower_cell = this.get_cell(index+1);
926 lower_cell = this.get_cell(index+1);
927 lower_text = lower_cell.get_text();
927 lower_text = lower_cell.get_text();
928 text = cell.get_text();
928 text = cell.get_text();
929 if (cell instanceof IPython.CodeCell) {
929 if (cell instanceof IPython.CodeCell) {
930 cell.set_text(text+'\n'+lower_text);
930 cell.set_text(text+'\n'+lower_text);
931 } else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) {
931 } else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) {
932 cell.edit();
932 cell.edit();
933 cell.set_text(text+'\n'+lower_text);
933 cell.set_text(text+'\n'+lower_text);
934 cell.render();
934 cell.render();
935 };
935 };
936 this.delete_cell(index+1);
936 this.delete_cell(index+1);
937 this.select(this.find_cell_index(cell));
937 this.select(this.find_cell_index(cell));
938 };
938 };
939 };
939 };
940
940
941
941
942 // Cell collapsing and output clearing
942 // Cell collapsing and output clearing
943
943
944 Notebook.prototype.collapse = function (index) {
944 Notebook.prototype.collapse = function (index) {
945 var i = this.index_or_selected(index);
945 var i = this.index_or_selected(index);
946 this.get_cell(i).collapse();
946 this.get_cell(i).collapse();
947 this.dirty = true;
947 this.dirty = true;
948 };
948 };
949
949
950
950
951 Notebook.prototype.expand = function (index) {
951 Notebook.prototype.expand = function (index) {
952 var i = this.index_or_selected(index);
952 var i = this.index_or_selected(index);
953 this.get_cell(i).expand();
953 this.get_cell(i).expand();
954 this.dirty = true;
954 this.dirty = true;
955 };
955 };
956
956
957
957
958 Notebook.prototype.toggle_output = function (index) {
958 Notebook.prototype.toggle_output = function (index) {
959 var i = this.index_or_selected(index);
959 var i = this.index_or_selected(index);
960 this.get_cell(i).toggle_output();
960 this.get_cell(i).toggle_output();
961 this.dirty = true;
961 this.dirty = true;
962 };
962 };
963
963
964
964
965 Notebook.prototype.toggle_output_scroll = function (index) {
965 Notebook.prototype.toggle_output_scroll = function (index) {
966 var i = this.index_or_selected(index);
966 var i = this.index_or_selected(index);
967 this.get_cell(i).toggle_output_scroll();
967 this.get_cell(i).toggle_output_scroll();
968 };
968 };
969
969
970
970
971 Notebook.prototype.collapse_all_output = function () {
971 Notebook.prototype.collapse_all_output = function () {
972 var ncells = this.ncells();
972 var ncells = this.ncells();
973 var cells = this.get_cells();
973 var cells = this.get_cells();
974 for (var i=0; i<ncells; i++) {
974 for (var i=0; i<ncells; i++) {
975 if (cells[i] instanceof IPython.CodeCell) {
975 if (cells[i] instanceof IPython.CodeCell) {
976 cells[i].output_area.collapse();
976 cells[i].output_area.collapse();
977 }
977 }
978 };
978 };
979 // this should not be set if the `collapse` key is removed from nbformat
979 // this should not be set if the `collapse` key is removed from nbformat
980 this.dirty = true;
980 this.dirty = true;
981 };
981 };
982
982
983
983
984 Notebook.prototype.scroll_all_output = function () {
984 Notebook.prototype.scroll_all_output = function () {
985 var ncells = this.ncells();
985 var ncells = this.ncells();
986 var cells = this.get_cells();
986 var cells = this.get_cells();
987 for (var i=0; i<ncells; i++) {
987 for (var i=0; i<ncells; i++) {
988 if (cells[i] instanceof IPython.CodeCell) {
988 if (cells[i] instanceof IPython.CodeCell) {
989 cells[i].output_area.expand();
989 cells[i].output_area.expand();
990 cells[i].output_area.scroll_if_long(20);
990 cells[i].output_area.scroll_if_long(20);
991 }
991 }
992 };
992 };
993 // this should not be set if the `collapse` key is removed from nbformat
993 // this should not be set if the `collapse` key is removed from nbformat
994 this.dirty = true;
994 this.dirty = true;
995 };
995 };
996
996
997
997
998 Notebook.prototype.expand_all_output = function () {
998 Notebook.prototype.expand_all_output = function () {
999 var ncells = this.ncells();
999 var ncells = this.ncells();
1000 var cells = this.get_cells();
1000 var cells = this.get_cells();
1001 for (var i=0; i<ncells; i++) {
1001 for (var i=0; i<ncells; i++) {
1002 if (cells[i] instanceof IPython.CodeCell) {
1002 if (cells[i] instanceof IPython.CodeCell) {
1003 cells[i].output_area.expand();
1003 cells[i].output_area.expand();
1004 cells[i].output_area.unscroll_area();
1004 cells[i].output_area.unscroll_area();
1005 }
1005 }
1006 };
1006 };
1007 // this should not be set if the `collapse` key is removed from nbformat
1007 // this should not be set if the `collapse` key is removed from nbformat
1008 this.dirty = true;
1008 this.dirty = true;
1009 };
1009 };
1010
1010
1011
1011
1012 Notebook.prototype.clear_all_output = function () {
1012 Notebook.prototype.clear_all_output = function () {
1013 var ncells = this.ncells();
1013 var ncells = this.ncells();
1014 var cells = this.get_cells();
1014 var cells = this.get_cells();
1015 for (var i=0; i<ncells; i++) {
1015 for (var i=0; i<ncells; i++) {
1016 if (cells[i] instanceof IPython.CodeCell) {
1016 if (cells[i] instanceof IPython.CodeCell) {
1017 cells[i].clear_output(true,true,true);
1017 cells[i].clear_output(true,true,true);
1018 // Make all In[] prompts blank, as well
1018 // Make all In[] prompts blank, as well
1019 // TODO: make this configurable (via checkbox?)
1019 // TODO: make this configurable (via checkbox?)
1020 cells[i].set_input_prompt();
1020 cells[i].set_input_prompt();
1021 }
1021 }
1022 };
1022 };
1023 this.dirty = true;
1023 this.dirty = true;
1024 };
1024 };
1025
1025
1026
1026
1027 // Other cell functions: line numbers, ...
1027 // Other cell functions: line numbers, ...
1028
1028
1029 Notebook.prototype.cell_toggle_line_numbers = function() {
1029 Notebook.prototype.cell_toggle_line_numbers = function() {
1030 this.get_selected_cell().toggle_line_numbers();
1030 this.get_selected_cell().toggle_line_numbers();
1031 };
1031 };
1032
1032
1033 // Kernel related things
1033 // Kernel related things
1034
1034
1035 Notebook.prototype.start_kernel = function () {
1035 Notebook.prototype.start_kernel = function () {
1036 var base_url = $('body').data('baseKernelUrl') + "kernels";
1036 var base_url = $('body').data('baseKernelUrl') + "kernels";
1037 this.kernel = new IPython.Kernel(base_url);
1037 this.kernel = new IPython.Kernel(base_url);
1038 this.kernel.start(this.notebook_id);
1038 this.kernel.start(this.notebook_id);
1039 // Now that the kernel has been created, tell the CodeCells about it.
1039 // Now that the kernel has been created, tell the CodeCells about it.
1040 var ncells = this.ncells();
1040 var ncells = this.ncells();
1041 for (var i=0; i<ncells; i++) {
1041 for (var i=0; i<ncells; i++) {
1042 var cell = this.get_cell(i);
1042 var cell = this.get_cell(i);
1043 if (cell instanceof IPython.CodeCell) {
1043 if (cell instanceof IPython.CodeCell) {
1044 cell.set_kernel(this.kernel)
1044 cell.set_kernel(this.kernel)
1045 };
1045 };
1046 };
1046 };
1047 };
1047 };
1048
1048
1049
1049
1050 Notebook.prototype.restart_kernel = function () {
1050 Notebook.prototype.restart_kernel = function () {
1051 var that = this;
1051 var that = this;
1052 var dialog = $('<div/>');
1052 var dialog = $('<div/>');
1053 dialog.html('Do you want to restart the current kernel? You will lose all variables defined in it.');
1053 dialog.html('Do you want to restart the current kernel? You will lose all variables defined in it.');
1054 $(document).append(dialog);
1054 $(document).append(dialog);
1055 dialog.dialog({
1055 dialog.dialog({
1056 resizable: false,
1056 resizable: false,
1057 modal: true,
1057 modal: true,
1058 title: "Restart kernel or continue running?",
1058 title: "Restart kernel or continue running?",
1059 closeText: '',
1059 closeText: '',
1060 buttons : {
1060 buttons : {
1061 "Restart": function () {
1061 "Restart": function () {
1062 that.kernel.restart();
1062 that.kernel.restart();
1063 $(this).dialog('close');
1063 $(this).dialog('close');
1064 },
1064 },
1065 "Continue running": function () {
1065 "Continue running": function () {
1066 $(this).dialog('close');
1066 $(this).dialog('close');
1067 }
1067 }
1068 }
1068 }
1069 });
1069 });
1070 };
1070 };
1071
1071
1072
1072
1073 Notebook.prototype.execute_selected_cell = function (options) {
1073 Notebook.prototype.execute_selected_cell = function (options) {
1074 // add_new: should a new cell be added if we are at the end of the nb
1074 // add_new: should a new cell be added if we are at the end of the nb
1075 // terminal: execute in terminal mode, which stays in the current cell
1075 // terminal: execute in terminal mode, which stays in the current cell
1076 default_options = {terminal: false, add_new: true};
1076 default_options = {terminal: false, add_new: true};
1077 $.extend(default_options, options);
1077 $.extend(default_options, options);
1078 var that = this;
1078 var that = this;
1079 var cell = that.get_selected_cell();
1079 var cell = that.get_selected_cell();
1080 var cell_index = that.find_cell_index(cell);
1080 var cell_index = that.find_cell_index(cell);
1081 if (cell instanceof IPython.CodeCell) {
1081 if (cell instanceof IPython.CodeCell) {
1082 cell.execute();
1082 cell.execute();
1083 } else if (cell instanceof IPython.HTMLCell) {
1083 } else if (cell instanceof IPython.HTMLCell) {
1084 cell.render();
1084 cell.render();
1085 }
1085 }
1086 if (default_options.terminal) {
1086 if (default_options.terminal) {
1087 cell.select_all();
1087 cell.select_all();
1088 } else {
1088 } else {
1089 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
1089 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
1090 that.insert_cell_below('code');
1090 that.insert_cell_below('code');
1091 // If we are adding a new cell at the end, scroll down to show it.
1091 // If we are adding a new cell at the end, scroll down to show it.
1092 that.scroll_to_bottom();
1092 that.scroll_to_bottom();
1093 } else {
1093 } else {
1094 that.select(cell_index+1);
1094 that.select(cell_index+1);
1095 };
1095 };
1096 };
1096 };
1097 this.dirty = true;
1097 this.dirty = true;
1098 };
1098 };
1099
1099
1100
1100
1101 Notebook.prototype.execute_cells_below = function () {
1101 Notebook.prototype.execute_cells_below = function () {
1102 this.execute_cell_range(this.get_selected_index(), this.ncells());
1102 this.execute_cell_range(this.get_selected_index(), this.ncells());
1103 that.scroll_to_bottom();
1103 that.scroll_to_bottom();
1104 };
1104 };
1105
1105
1106 Notebook.prototype.execute_cells_above = function () {
1106 Notebook.prototype.execute_cells_above = function () {
1107 this.execute_cell_range(0, this.get_selected_index());
1107 this.execute_cell_range(0, this.get_selected_index());
1108 };
1108 };
1109
1109
1110 Notebook.prototype.execute_all_cells = function () {
1110 Notebook.prototype.execute_all_cells = function () {
1111 this.execute_cell_range(0, this.ncells());
1111 this.execute_cell_range(0, this.ncells());
1112 that.scroll_to_bottom();
1112 that.scroll_to_bottom();
1113 };
1113 };
1114
1114
1115 Notebook.prototype.execute_cell_range = function (start, end) {
1115 Notebook.prototype.execute_cell_range = function (start, end) {
1116 for (var i=start; i<end; i++) {
1116 for (var i=start; i<end; i++) {
1117 this.select(i);
1117 this.select(i);
1118 this.execute_selected_cell({add_new:false});
1118 this.execute_selected_cell({add_new:false});
1119 };
1119 };
1120 };
1120 };
1121
1121
1122 // Persistance and loading
1122 // Persistance and loading
1123
1123
1124 Notebook.prototype.get_notebook_id = function () {
1124 Notebook.prototype.get_notebook_id = function () {
1125 return this.notebook_id;
1125 return this.notebook_id;
1126 };
1126 };
1127
1127
1128
1128
1129 Notebook.prototype.get_notebook_name = function () {
1129 Notebook.prototype.get_notebook_name = function () {
1130 return this.notebook_name;
1130 return this.notebook_name;
1131 };
1131 };
1132
1132
1133
1133
1134 Notebook.prototype.set_notebook_name = function (name) {
1134 Notebook.prototype.set_notebook_name = function (name) {
1135 this.notebook_name = name;
1135 this.notebook_name = name;
1136 };
1136 };
1137
1137
1138
1138
1139 Notebook.prototype.test_notebook_name = function (nbname) {
1139 Notebook.prototype.test_notebook_name = function (nbname) {
1140 nbname = nbname || '';
1140 nbname = nbname || '';
1141 if (this.notebook_name_blacklist_re.test(nbname) == false && nbname.length>0) {
1141 if (this.notebook_name_blacklist_re.test(nbname) == false && nbname.length>0) {
1142 return true;
1142 return true;
1143 } else {
1143 } else {
1144 return false;
1144 return false;
1145 };
1145 };
1146 };
1146 };
1147
1147
1148
1148
1149 Notebook.prototype.fromJSON = function (data) {
1149 Notebook.prototype.fromJSON = function (data) {
1150 var ncells = this.ncells();
1150 var ncells = this.ncells();
1151 var i;
1151 var i;
1152 for (i=0; i<ncells; i++) {
1152 for (i=0; i<ncells; i++) {
1153 // Always delete cell 0 as they get renumbered as they are deleted.
1153 // Always delete cell 0 as they get renumbered as they are deleted.
1154 this.delete_cell(0);
1154 this.delete_cell(0);
1155 };
1155 };
1156 // Save the metadata and name.
1156 // Save the metadata and name.
1157 this.metadata = data.metadata;
1157 this.metadata = data.metadata;
1158 this.notebook_name = data.metadata.name;
1158 this.notebook_name = data.metadata.name;
1159 // Only handle 1 worksheet for now.
1159 // Only handle 1 worksheet for now.
1160 var worksheet = data.worksheets[0];
1160 var worksheet = data.worksheets[0];
1161 if (worksheet !== undefined) {
1161 if (worksheet !== undefined) {
1162 if (worksheet.metadata) {
1162 if (worksheet.metadata) {
1163 this.worksheet_metadata = worksheet.metadata;
1163 this.worksheet_metadata = worksheet.metadata;
1164 }
1164 }
1165 var new_cells = worksheet.cells;
1165 var new_cells = worksheet.cells;
1166 ncells = new_cells.length;
1166 ncells = new_cells.length;
1167 var cell_data = null;
1167 var cell_data = null;
1168 var new_cell = null;
1168 var new_cell = null;
1169 for (i=0; i<ncells; i++) {
1169 for (i=0; i<ncells; i++) {
1170 cell_data = new_cells[i];
1170 cell_data = new_cells[i];
1171 // VERSIONHACK: plaintext -> raw
1171 // VERSIONHACK: plaintext -> raw
1172 // handle never-released plaintext name for raw cells
1172 // handle never-released plaintext name for raw cells
1173 if (cell_data.cell_type === 'plaintext'){
1173 if (cell_data.cell_type === 'plaintext'){
1174 cell_data.cell_type = 'raw';
1174 cell_data.cell_type = 'raw';
1175 }
1175 }
1176
1176
1177 new_cell = this.insert_cell_below(cell_data.cell_type);
1177 new_cell = this.insert_cell_below(cell_data.cell_type);
1178 new_cell.fromJSON(cell_data);
1178 new_cell.fromJSON(cell_data);
1179 };
1179 };
1180 };
1180 };
1181 if (data.worksheets.length > 1) {
1181 if (data.worksheets.length > 1) {
1182 var dialog = $('<div/>');
1182 var dialog = $('<div/>');
1183 dialog.html("This notebook has " + data.worksheets.length + " worksheets, " +
1183 dialog.html("This notebook has " + data.worksheets.length + " worksheets, " +
1184 "but this version of IPython can only handle the first. " +
1184 "but this version of IPython can only handle the first. " +
1185 "If you save this notebook, worksheets after the first will be lost."
1185 "If you save this notebook, worksheets after the first will be lost."
1186 );
1186 );
1187 this.element.append(dialog);
1187 this.element.append(dialog);
1188 dialog.dialog({
1188 dialog.dialog({
1189 resizable: false,
1189 resizable: false,
1190 modal: true,
1190 modal: true,
1191 title: "Multiple worksheets",
1191 title: "Multiple worksheets",
1192 closeText: "",
1192 closeText: "",
1193 close: function(event, ui) {$(this).dialog('destroy').remove();},
1193 close: function(event, ui) {$(this).dialog('destroy').remove();},
1194 buttons : {
1194 buttons : {
1195 "OK": function () {
1195 "OK": function () {
1196 $(this).dialog('close');
1196 $(this).dialog('close');
1197 }
1197 }
1198 },
1198 },
1199 width: 400
1199 width: 400
1200 });
1200 });
1201 }
1201 }
1202 };
1202 };
1203
1203
1204
1204
1205 Notebook.prototype.toJSON = function () {
1205 Notebook.prototype.toJSON = function () {
1206 var cells = this.get_cells();
1206 var cells = this.get_cells();
1207 var ncells = cells.length;
1207 var ncells = cells.length;
1208 var cell_array = new Array(ncells);
1208 var cell_array = new Array(ncells);
1209 for (var i=0; i<ncells; i++) {
1209 for (var i=0; i<ncells; i++) {
1210 cell_array[i] = cells[i].toJSON();
1210 cell_array[i] = cells[i].toJSON();
1211 };
1211 };
1212 var data = {
1212 var data = {
1213 // Only handle 1 worksheet for now.
1213 // Only handle 1 worksheet for now.
1214 worksheets : [{
1214 worksheets : [{
1215 cells: cell_array,
1215 cells: cell_array,
1216 metadata: this.worksheet_metadata
1216 metadata: this.worksheet_metadata
1217 }],
1217 }],
1218 metadata : this.metadata
1218 metadata : this.metadata
1219 };
1219 };
1220 return data;
1220 return data;
1221 };
1221 };
1222
1222
1223 Notebook.prototype.save_notebook = function () {
1223 Notebook.prototype.save_notebook = function () {
1224 // We may want to move the name/id/nbformat logic inside toJSON?
1224 // We may want to move the name/id/nbformat logic inside toJSON?
1225 var data = this.toJSON();
1225 var data = this.toJSON();
1226 data.metadata.name = this.notebook_name;
1226 data.metadata.name = this.notebook_name;
1227 data.nbformat = this.nbformat;
1227 data.nbformat = this.nbformat;
1228 data.nbformat_minor = this.nbformat_minor;
1228 data.nbformat_minor = this.nbformat_minor;
1229 // We do the call with settings so we can set cache to false.
1229 // We do the call with settings so we can set cache to false.
1230 var settings = {
1230 var settings = {
1231 processData : false,
1231 processData : false,
1232 cache : false,
1232 cache : false,
1233 type : "PUT",
1233 type : "PUT",
1234 data : JSON.stringify(data),
1234 data : JSON.stringify(data),
1235 headers : {'Content-Type': 'application/json'},
1235 headers : {'Content-Type': 'application/json'},
1236 success : $.proxy(this.save_notebook_success,this),
1236 success : $.proxy(this.save_notebook_success,this),
1237 error : $.proxy(this.save_notebook_error,this)
1237 error : $.proxy(this.save_notebook_error,this)
1238 };
1238 };
1239 $([IPython.events]).trigger('notebook_saving.Notebook');
1239 $([IPython.events]).trigger('notebook_saving.Notebook');
1240 var url = $('body').data('baseProjectUrl') + 'notebooks/' + this.notebook_id;
1240 var url = $('body').data('baseProjectUrl') + 'notebooks/' + this.notebook_id;
1241 $.ajax(url, settings);
1241 $.ajax(url, settings);
1242 };
1242 };
1243
1243
1244
1244
1245 Notebook.prototype.save_notebook_success = function (data, status, xhr) {
1245 Notebook.prototype.save_notebook_success = function (data, status, xhr) {
1246 this.dirty = false;
1246 this.dirty = false;
1247 $([IPython.events]).trigger('notebook_saved.Notebook');
1247 $([IPython.events]).trigger('notebook_saved.Notebook');
1248 };
1248 };
1249
1249
1250
1250
1251 Notebook.prototype.save_notebook_error = function (xhr, status, error_msg) {
1251 Notebook.prototype.save_notebook_error = function (xhr, status, error_msg) {
1252 $([IPython.events]).trigger('notebook_save_failed.Notebook');
1252 $([IPython.events]).trigger('notebook_save_failed.Notebook');
1253 };
1253 };
1254
1254
1255
1255
1256 Notebook.prototype.load_notebook = function (notebook_id) {
1256 Notebook.prototype.load_notebook = function (notebook_id) {
1257 var that = this;
1257 var that = this;
1258 this.notebook_id = notebook_id;
1258 this.notebook_id = notebook_id;
1259 // We do the call with settings so we can set cache to false.
1259 // We do the call with settings so we can set cache to false.
1260 var settings = {
1260 var settings = {
1261 processData : false,
1261 processData : false,
1262 cache : false,
1262 cache : false,
1263 type : "GET",
1263 type : "GET",
1264 dataType : "json",
1264 dataType : "json",
1265 success : $.proxy(this.load_notebook_success,this),
1265 success : $.proxy(this.load_notebook_success,this),
1266 error : $.proxy(this.load_notebook_error,this),
1266 error : $.proxy(this.load_notebook_error,this),
1267 };
1267 };
1268 $([IPython.events]).trigger('notebook_loading.Notebook');
1268 $([IPython.events]).trigger('notebook_loading.Notebook');
1269 var url = $('body').data('baseProjectUrl') + 'notebooks/' + this.notebook_id;
1269 var url = $('body').data('baseProjectUrl') + 'notebooks/' + this.notebook_id;
1270 $.ajax(url, settings);
1270 $.ajax(url, settings);
1271 };
1271 };
1272
1272
1273
1273
1274 Notebook.prototype.load_notebook_success = function (data, status, xhr) {
1274 Notebook.prototype.load_notebook_success = function (data, status, xhr) {
1275 this.fromJSON(data);
1275 this.fromJSON(data);
1276 if (this.ncells() === 0) {
1276 if (this.ncells() === 0) {
1277 this.insert_cell_below('code');
1277 this.insert_cell_below('code');
1278 };
1278 };
1279 this.dirty = false;
1279 this.dirty = false;
1280 this.select(0);
1280 this.select(0);
1281 this.scroll_to_top();
1281 this.scroll_to_top();
1282 if (data.orig_nbformat !== undefined && data.nbformat !== data.orig_nbformat) {
1282 if (data.orig_nbformat !== undefined && data.nbformat !== data.orig_nbformat) {
1283 msg = "This notebook has been converted from an older " +
1283 msg = "This notebook has been converted from an older " +
1284 "notebook format (v"+data.orig_nbformat+") to the current notebook " +
1284 "notebook format (v"+data.orig_nbformat+") to the current notebook " +
1285 "format (v"+data.nbformat+"). The next time you save this notebook, the " +
1285 "format (v"+data.nbformat+"). The next time you save this notebook, the " +
1286 "newer notebook format will be used and older verions of IPython " +
1286 "newer notebook format will be used and older verions of IPython " +
1287 "may not be able to read it. To keep the older version, close the " +
1287 "may not be able to read it. To keep the older version, close the " +
1288 "notebook without saving it.";
1288 "notebook without saving it.";
1289 var dialog = $('<div/>');
1289 var dialog = $('<div/>');
1290 dialog.html(msg);
1290 dialog.html(msg);
1291 this.element.append(dialog);
1291 this.element.append(dialog);
1292 dialog.dialog({
1292 dialog.dialog({
1293 resizable: false,
1293 resizable: false,
1294 modal: true,
1294 modal: true,
1295 title: "Notebook converted",
1295 title: "Notebook converted",
1296 closeText: "",
1296 closeText: "",
1297 close: function(event, ui) {$(this).dialog('destroy').remove();},
1297 close: function(event, ui) {$(this).dialog('destroy').remove();},
1298 buttons : {
1298 buttons : {
1299 "OK": function () {
1299 "OK": function () {
1300 $(this).dialog('close');
1300 $(this).dialog('close');
1301 }
1301 }
1302 },
1302 },
1303 width: 400
1303 width: 400
1304 });
1304 });
1305 } else if (data.orig_nbformat_minor !== undefined && data.nbformat_minor !== data.orig_nbformat_minor) {
1305 } else if (data.orig_nbformat_minor !== undefined && data.nbformat_minor !== data.orig_nbformat_minor) {
1306 var that = this;
1306 var that = this;
1307 var orig_vs = 'v' + data.nbformat + '.' + data.orig_nbformat_minor;
1307 var orig_vs = 'v' + data.nbformat + '.' + data.orig_nbformat_minor;
1308 var this_vs = 'v' + data.nbformat + '.' + this.nbformat_minor;
1308 var this_vs = 'v' + data.nbformat + '.' + this.nbformat_minor;
1309 msg = "This notebook is version " + orig_vs + ", but we only fully support up to " +
1309 msg = "This notebook is version " + orig_vs + ", but we only fully support up to " +
1310 this_vs + ". You can still work with this notebook, but some features " +
1310 this_vs + ". You can still work with this notebook, but some features " +
1311 "introduced in later notebook versions may not be available."
1311 "introduced in later notebook versions may not be available."
1312
1312
1313 var dialog = $('<div/>');
1313 var dialog = $('<div/>');
1314 dialog.html(msg);
1314 dialog.html(msg);
1315 this.element.append(dialog);
1315 this.element.append(dialog);
1316 dialog.dialog({
1316 dialog.dialog({
1317 resizable: false,
1317 resizable: false,
1318 modal: true,
1318 modal: true,
1319 title: "Newer Notebook",
1319 title: "Newer Notebook",
1320 closeText: "",
1320 closeText: "",
1321 close: function(event, ui) {$(this).dialog('destroy').remove();},
1321 close: function(event, ui) {$(this).dialog('destroy').remove();},
1322 buttons : {
1322 buttons : {
1323 "OK": function () {
1323 "OK": function () {
1324 $(this).dialog('close');
1324 $(this).dialog('close');
1325 }
1325 }
1326 },
1326 },
1327 width: 400
1327 width: 400
1328 });
1328 });
1329
1329
1330 }
1330 }
1331 // Create the kernel after the notebook is completely loaded to prevent
1331 // Create the kernel after the notebook is completely loaded to prevent
1332 // code execution upon loading, which is a security risk.
1332 // code execution upon loading, which is a security risk.
1333 if (! this.read_only) {
1333 if (! this.read_only) {
1334 this.start_kernel();
1334 this.start_kernel();
1335 }
1335 }
1336 $([IPython.events]).trigger('notebook_loaded.Notebook');
1336 $([IPython.events]).trigger('notebook_loaded.Notebook');
1337 };
1337 };
1338
1338
1339
1339
1340 Notebook.prototype.load_notebook_error = function (xhr, textStatus, errorThrow) {
1340 Notebook.prototype.load_notebook_error = function (xhr, textStatus, errorThrow) {
1341 if (xhr.status === 500) {
1341 if (xhr.status === 500) {
1342 msg = "An error occurred while loading this notebook. Most likely " +
1342 msg = "An error occurred while loading this notebook. Most likely " +
1343 "this notebook is in a newer format than is supported by this " +
1343 "this notebook is in a newer format than is supported by this " +
1344 "version of IPython. This version can load notebook formats " +
1344 "version of IPython. This version can load notebook formats " +
1345 "v"+this.nbformat+" or earlier.";
1345 "v"+this.nbformat+" or earlier.";
1346 var dialog = $('<div/>');
1346 var dialog = $('<div/>');
1347 dialog.html(msg);
1347 dialog.html(msg);
1348 this.element.append(dialog);
1348 this.element.append(dialog);
1349 dialog.dialog({
1349 dialog.dialog({
1350 resizable: false,
1350 resizable: false,
1351 modal: true,
1351 modal: true,
1352 title: "Error loading notebook",
1352 title: "Error loading notebook",
1353 closeText: "",
1353 closeText: "",
1354 close: function(event, ui) {$(this).dialog('destroy').remove();},
1354 close: function(event, ui) {$(this).dialog('destroy').remove();},
1355 buttons : {
1355 buttons : {
1356 "OK": function () {
1356 "OK": function () {
1357 $(this).dialog('close');
1357 $(this).dialog('close');
1358 }
1358 }
1359 },
1359 },
1360 width: 400
1360 width: 400
1361 });
1361 });
1362 }
1362 }
1363 }
1363 }
1364
1364
1365 IPython.Notebook = Notebook;
1365 IPython.Notebook = Notebook;
1366
1366
1367
1367
1368 return IPython;
1368 return IPython;
1369
1369
1370 }(IPython));
1370 }(IPython));
1371
1371
@@ -1,226 +1,226
1 {% extends page.html %}
1 {% extends page.html %}
2 {% block stylesheet %}
2 {% block stylesheet %}
3
3
4 {% if mathjax_url %}
4 {% if mathjax_url %}
5 <script type="text/javascript" src="{{mathjax_url}}?config=TeX-AMS_HTML-full&delayStartupUntil=configured" charset="utf-8"></script>
5 <script type="text/javascript" src="{{mathjax_url}}?config=TeX-AMS_HTML-full&delayStartupUntil=configured" charset="utf-8"></script>
6 {% end %}
6 {% end %}
7 <script type="text/javascript">
7 <script type="text/javascript">
8 // MathJax disabled, set as null to distingish from *missing* MathJax,
8 // MathJax disabled, set as null to distingish from *missing* MathJax,
9 // where it will be undefined, and should prompt a dialog later.
9 // where it will be undefined, and should prompt a dialog later.
10 window.mathjax_url = "{{mathjax_url}}";
10 window.mathjax_url = "{{mathjax_url}}";
11 </script>
11 </script>
12
12
13 <link rel="stylesheet" href="{{ static_url("codemirror/lib/codemirror.css") }}">
13 <link rel="stylesheet" href="{{ static_url("codemirror/lib/codemirror.css") }}">
14 <link rel="stylesheet" href="{{ static_url("codemirror/theme/ipython.css") }}">
14 <link rel="stylesheet" href="{{ static_url("codemirror/theme/ipython.css") }}">
15
15
16 <link rel="stylesheet" href="{{ static_url("prettify/prettify.css") }}"/>
16 <link rel="stylesheet" href="{{ static_url("prettify/prettify.css") }}"/>
17
17
18 <link rel="stylesheet" href="{{ static_url("css/notebook.css") }}" type="text/css" />
18 <link rel="stylesheet" href="{{ static_url("css/notebook.css") }}" type="text/css" />
19 <link rel="stylesheet" href="{{ static_url("css/tooltip.css") }}" type="text/css" />
19 <link rel="stylesheet" href="{{ static_url("css/tooltip.css") }}" type="text/css" />
20 <link rel="stylesheet" href="{{ static_url("css/renderedhtml.css") }}" type="text/css" />
20 <link rel="stylesheet" href="{{ static_url("css/renderedhtml.css") }}" type="text/css" />
21
21
22 <link rel="stylesheet" href="{{ static_url("css/printnotebook.css") }}" type="text/css" media="print"/>
22 <link rel="stylesheet" href="{{ static_url("css/printnotebook.css") }}" type="text/css" media="print"/>
23
23
24 {% end %}
24 {% end %}
25
25
26
26
27 {% block params %}
27 {% block params %}
28
28
29 data-project={{project}}
29 data-project={{project}}
30 data-base-project-url={{base_project_url}}
30 data-base-project-url={{base_project_url}}
31 data-base-kernel-url={{base_kernel_url}}
31 data-base-kernel-url={{base_kernel_url}}
32 data-read-only={{read_only and not logged_in}}
32 data-read-only={{read_only and not logged_in}}
33 data-notebook-id={{notebook_id}}
33 data-notebook-id={{notebook_id}}
34
34
35 {% end %}
35 {% end %}
36
36
37
37
38 {% block header %}
38 {% block header %}
39
39
40 <span id="save_widget">
40 <span id="save_widget">
41 <span id="notebook_name"></span>
41 <span id="notebook_name"></span>
42 <span id="save_status"></span>
42 <span id="save_status"></span>
43 </span>
43 </span>
44
44
45 {% end %}
45 {% end %}
46
46
47
47
48 {% block site %}
48 {% block site %}
49
49
50 <div id="menubar_container">
50 <div id="menubar_container">
51 <div id="menubar">
51 <div id="menubar">
52 <ul id="menus">
52 <ul id="menus">
53 <li><a href="#">File</a>
53 <li><a href="#">File</a>
54 <ul>
54 <ul>
55 <li id="new_notebook"><a href="#">New</a></li>
55 <li id="new_notebook"><a href="#">New</a></li>
56 <li id="open_notebook"><a href="#">Open...</a></li>
56 <li id="open_notebook"><a href="#">Open...</a></li>
57 <hr/>
57 <hr/>
58 <li id="copy_notebook"><a href="#">Make a Copy...</a></li>
58 <li id="copy_notebook"><a href="#">Make a Copy...</a></li>
59 <li id="rename_notebook"><a href="#">Rename...</a></li>
59 <li id="rename_notebook"><a href="#">Rename...</a></li>
60 <li id="save_notebook"><a href="#">Save</a></li>
60 <li id="save_notebook"><a href="#">Save</a></li>
61 <hr/>
61 <hr/>
62 <li><a href="#">Download as</a>
62 <li><a href="#">Download as</a>
63 <ul>
63 <ul>
64 <li id="download_ipynb"><a href="#">IPython (.ipynb)</a></li>
64 <li id="download_ipynb"><a href="#">IPython (.ipynb)</a></li>
65 <li id="download_py"><a href="#">Python (.py)</a></li>
65 <li id="download_py"><a href="#">Python (.py)</a></li>
66 </ul>
66 </ul>
67 </li>
67 </li>
68 <hr/>
68 <hr/>
69 <li id="print_notebook"><a href="/{{notebook_id}}/print" target="_blank">Print View</a></li>
69 <li id="print_notebook"><a href="/{{notebook_id}}/print" target="_blank">Print View</a></li>
70 <hr/>
70 <hr/>
71 <li id="kill_and_exit"><a href="#" >Close and halt</a></li>
71 <li id="kill_and_exit"><a href="#" >Close and halt</a></li>
72 </ul>
72 </ul>
73 </li>
73 </li>
74 <li><a href="#">Edit</a>
74 <li><a href="#">Edit</a>
75 <ul>
75 <ul>
76 <li id="cut_cell"><a href="#">Cut Cell</a></li>
76 <li id="cut_cell"><a href="#">Cut Cell</a></li>
77 <li id="copy_cell"><a href="#">Copy Cell</a></li>
77 <li id="copy_cell"><a href="#">Copy Cell</a></li>
78 <li id="paste_cell" class="ui-state-disabled"><a href="#">Paste Cell</a></li>
79 <li id="paste_cell_above" class="ui-state-disabled"><a href="#">Paste Cell Above</a></li>
78 <li id="paste_cell_above" class="ui-state-disabled"><a href="#">Paste Cell Above</a></li>
80 <li id="paste_cell_below" class="ui-state-disabled"><a href="#">Paste Cell Below</a></li>
79 <li id="paste_cell_below" class="ui-state-disabled"><a href="#">Paste Cell Below</a></li>
80 <li id="paste_cell_replace" class="ui-state-disabled"><a href="#">Paste Cell Replace</a></li>
81 <li id="delete_cell"><a href="#">Delete</a></li>
81 <li id="delete_cell"><a href="#">Delete</a></li>
82 <hr/>
82 <hr/>
83 <li id="split_cell"><a href="#">Split Cell</a></li>
83 <li id="split_cell"><a href="#">Split Cell</a></li>
84 <li id="merge_cell_above"><a href="#">Merge Cell Above</a></li>
84 <li id="merge_cell_above"><a href="#">Merge Cell Above</a></li>
85 <li id="merge_cell_below"><a href="#">Merge Cell Below</a></li>
85 <li id="merge_cell_below"><a href="#">Merge Cell Below</a></li>
86 <hr/>
86 <hr/>
87 <li id="move_cell_up"><a href="#">Move Cell Up</a></li>
87 <li id="move_cell_up"><a href="#">Move Cell Up</a></li>
88 <li id="move_cell_down"><a href="#">Move Cell Down</a></li>
88 <li id="move_cell_down"><a href="#">Move Cell Down</a></li>
89 <hr/>
89 <hr/>
90 <li id="select_previous"><a href="#">Select Previous Cell</a></li>
90 <li id="select_previous"><a href="#">Select Previous Cell</a></li>
91 <li id="select_next"><a href="#">Select Next Cell</a></li>
91 <li id="select_next"><a href="#">Select Next Cell</a></li>
92 </ul>
92 </ul>
93 </li>
93 </li>
94 <li><a href="#">View</a>
94 <li><a href="#">View</a>
95 <ul>
95 <ul>
96 <li id="toggle_header"><a href="#">Toggle Header</a></li>
96 <li id="toggle_header"><a href="#">Toggle Header</a></li>
97 <li id="toggle_toolbar"><a href="#">Toggle Toolbar</a></li>
97 <li id="toggle_toolbar"><a href="#">Toggle Toolbar</a></li>
98 </ul>
98 </ul>
99 </li>
99 </li>
100 <li><a href="#">Insert</a>
100 <li><a href="#">Insert</a>
101 <ul>
101 <ul>
102 <li id="insert_cell_above"><a href="#">Insert Cell Above</a></li>
102 <li id="insert_cell_above"><a href="#">Insert Cell Above</a></li>
103 <li id="insert_cell_below"><a href="#">Insert Cell Below</a></li>
103 <li id="insert_cell_below"><a href="#">Insert Cell Below</a></li>
104 </ul>
104 </ul>
105 </li>
105 </li>
106 <li><a href="#">Cell</a>
106 <li><a href="#">Cell</a>
107 <ul>
107 <ul>
108 <li id="run_cell"><a href="#">Run</a></li>
108 <li id="run_cell"><a href="#">Run</a></li>
109 <li id="run_cell_in_place"><a href="#">Run in Place</a></li>
109 <li id="run_cell_in_place"><a href="#">Run in Place</a></li>
110 <li id="run_all_cells"><a href="#">Run All</a></li>
110 <li id="run_all_cells"><a href="#">Run All</a></li>
111 <li id="run_all_cells_above"><a href="#">Run All Above</a></li>
111 <li id="run_all_cells_above"><a href="#">Run All Above</a></li>
112 <li id="run_all_cells_below"><a href="#">Run All Below</a></li>
112 <li id="run_all_cells_below"><a href="#">Run All Below</a></li>
113 <hr/>
113 <hr/>
114 <li id="to_code"><a href="#">Code</a></li>
114 <li id="to_code"><a href="#">Code</a></li>
115 <li id="to_markdown"><a href="#">Markdown </a></li>
115 <li id="to_markdown"><a href="#">Markdown </a></li>
116 <li id="to_raw"><a href="#">Raw Text</a></li>
116 <li id="to_raw"><a href="#">Raw Text</a></li>
117 <li id="to_heading1"><a href="#">Heading 1</a></li>
117 <li id="to_heading1"><a href="#">Heading 1</a></li>
118 <li id="to_heading2"><a href="#">Heading 2</a></li>
118 <li id="to_heading2"><a href="#">Heading 2</a></li>
119 <li id="to_heading3"><a href="#">Heading 3</a></li>
119 <li id="to_heading3"><a href="#">Heading 3</a></li>
120 <li id="to_heading4"><a href="#">Heading 4</a></li>
120 <li id="to_heading4"><a href="#">Heading 4</a></li>
121 <li id="to_heading5"><a href="#">Heading 5</a></li>
121 <li id="to_heading5"><a href="#">Heading 5</a></li>
122 <li id="to_heading6"><a href="#">Heading 6</a></li>
122 <li id="to_heading6"><a href="#">Heading 6</a></li>
123 <hr/>
123 <hr/>
124 <li id="toggle_output"><a href="#">Toggle Current Output</a></li>
124 <li id="toggle_output"><a href="#">Toggle Current Output</a></li>
125 <li id="all_outputs"><a href="#">All Output</a>
125 <li id="all_outputs"><a href="#">All Output</a>
126 <ul>
126 <ul>
127 <li id="expand_all_output"><a href="#">Expand</a></li>
127 <li id="expand_all_output"><a href="#">Expand</a></li>
128 <li id="scroll_all_output"><a href="#">Scroll Long</a></li>
128 <li id="scroll_all_output"><a href="#">Scroll Long</a></li>
129 <li id="collapse_all_output"><a href="#">Collapse</a></li>
129 <li id="collapse_all_output"><a href="#">Collapse</a></li>
130 <li id="clear_all_output"><a href="#">Clear</a></li>
130 <li id="clear_all_output"><a href="#">Clear</a></li>
131 </ul>
131 </ul>
132 </li>
132 </li>
133 </ul>
133 </ul>
134 </li>
134 </li>
135 <li><a href="#">Kernel</a>
135 <li><a href="#">Kernel</a>
136 <ul>
136 <ul>
137 <li id="int_kernel"><a href="#">Interrupt</a></li>
137 <li id="int_kernel"><a href="#">Interrupt</a></li>
138 <li id="restart_kernel"><a href="#">Restart</a></li>
138 <li id="restart_kernel"><a href="#">Restart</a></li>
139 </ul>
139 </ul>
140 </li>
140 </li>
141 <li><a href="#">Help</a>
141 <li><a href="#">Help</a>
142 <ul>
142 <ul>
143 <li><a href="http://ipython.org/documentation.html" target="_blank">IPython Help</a></li>
143 <li><a href="http://ipython.org/documentation.html" target="_blank">IPython Help</a></li>
144 <li><a href="http://ipython.org/ipython-doc/stable/interactive/htmlnotebook.html" target="_blank">Notebook Help</a></li>
144 <li><a href="http://ipython.org/ipython-doc/stable/interactive/htmlnotebook.html" target="_blank">Notebook Help</a></li>
145 <li id="keyboard_shortcuts"><a href="#">Keyboard Shortcuts</a></li>
145 <li id="keyboard_shortcuts"><a href="#">Keyboard Shortcuts</a></li>
146 <hr/>
146 <hr/>
147 <li><a href="http://docs.python.org" target="_blank">Python</a></li>
147 <li><a href="http://docs.python.org" target="_blank">Python</a></li>
148 <li><a href="http://docs.scipy.org/doc/numpy/reference/" target="_blank">NumPy</a></li>
148 <li><a href="http://docs.scipy.org/doc/numpy/reference/" target="_blank">NumPy</a></li>
149 <li><a href="http://docs.scipy.org/doc/scipy/reference/" target="_blank">SciPy</a></li>
149 <li><a href="http://docs.scipy.org/doc/scipy/reference/" target="_blank">SciPy</a></li>
150 <li><a href="http://docs.sympy.org/dev/index.html" target="_blank">SymPy</a></li>
150 <li><a href="http://docs.sympy.org/dev/index.html" target="_blank">SymPy</a></li>
151 <li><a href="http://matplotlib.sourceforge.net/" target="_blank">Matplotlib</a></li>
151 <li><a href="http://matplotlib.sourceforge.net/" target="_blank">Matplotlib</a></li>
152 </ul>
152 </ul>
153 </li>
153 </li>
154 </ul>
154 </ul>
155
155
156 </div>
156 </div>
157 <div id="notification_area">
157 <div id="notification_area">
158 </div>
158 </div>
159 </div>
159 </div>
160
160
161
161
162 <div id="maintoolbar"></div>
162 <div id="maintoolbar"></div>
163
163
164 <div id="main_app">
164 <div id="main_app">
165
165
166 <div id="notebook_panel">
166 <div id="notebook_panel">
167 <div id="notebook"></div>
167 <div id="notebook"></div>
168 <div id="pager_splitter"></div>
168 <div id="pager_splitter"></div>
169 <div id="pager_container">
169 <div id="pager_container">
170 <div id='pager_button_area'>
170 <div id='pager_button_area'>
171 </div>
171 </div>
172 <div id="pager"></div>
172 <div id="pager"></div>
173 </div>
173 </div>
174 </div>
174 </div>
175
175
176 </div>
176 </div>
177 <div id='tooltip' class='ipython_tooltip ui-corner-all' style='display:none'></div>
177 <div id='tooltip' class='ipython_tooltip ui-corner-all' style='display:none'></div>
178
178
179
179
180 {% end %}
180 {% end %}
181
181
182
182
183 {% block script %}
183 {% block script %}
184
184
185 <script src="{{ static_url("codemirror/lib/codemirror.js") }}" charset="utf-8"></script>
185 <script src="{{ static_url("codemirror/lib/codemirror.js") }}" charset="utf-8"></script>
186 <script src="{{ static_url("codemirror/lib/util/loadmode.js") }}" charset="utf-8"></script>
186 <script src="{{ static_url("codemirror/lib/util/loadmode.js") }}" charset="utf-8"></script>
187 <script src="{{ static_url("codemirror/lib/util/multiplex.js") }}" charset="utf-8"></script>
187 <script src="{{ static_url("codemirror/lib/util/multiplex.js") }}" charset="utf-8"></script>
188 <script src="{{ static_url("codemirror/mode/python/python.js") }}" charset="utf-8"></script>
188 <script src="{{ static_url("codemirror/mode/python/python.js") }}" charset="utf-8"></script>
189 <script src="{{ static_url("codemirror/mode/htmlmixed/htmlmixed.js") }}" charset="utf-8"></script>
189 <script src="{{ static_url("codemirror/mode/htmlmixed/htmlmixed.js") }}" charset="utf-8"></script>
190 <script src="{{ static_url("codemirror/mode/xml/xml.js") }}" charset="utf-8"></script>
190 <script src="{{ static_url("codemirror/mode/xml/xml.js") }}" charset="utf-8"></script>
191 <script src="{{ static_url("codemirror/mode/javascript/javascript.js") }}" charset="utf-8"></script>
191 <script src="{{ static_url("codemirror/mode/javascript/javascript.js") }}" charset="utf-8"></script>
192 <script src="{{ static_url("codemirror/mode/css/css.js") }}" charset="utf-8"></script>
192 <script src="{{ static_url("codemirror/mode/css/css.js") }}" charset="utf-8"></script>
193 <script src="{{ static_url("codemirror/mode/rst/rst.js") }}" charset="utf-8"></script>
193 <script src="{{ static_url("codemirror/mode/rst/rst.js") }}" charset="utf-8"></script>
194 <script src="{{ static_url("codemirror/mode/markdown/markdown.js") }}" charset="utf-8"></script>
194 <script src="{{ static_url("codemirror/mode/markdown/markdown.js") }}" charset="utf-8"></script>
195
195
196 <script src="{{ static_url("pagedown/Markdown.Converter.js") }}" charset="utf-8"></script>
196 <script src="{{ static_url("pagedown/Markdown.Converter.js") }}" charset="utf-8"></script>
197
197
198 <script src="{{ static_url("prettify/prettify.js") }}" charset="utf-8"></script>
198 <script src="{{ static_url("prettify/prettify.js") }}" charset="utf-8"></script>
199 <script src="{{ static_url("dateformat/date.format.js") }}" charset="utf-8"></script>
199 <script src="{{ static_url("dateformat/date.format.js") }}" charset="utf-8"></script>
200
200
201 <script src="{{ static_url("js/events.js") }}" type="text/javascript" charset="utf-8"></script>
201 <script src="{{ static_url("js/events.js") }}" type="text/javascript" charset="utf-8"></script>
202 <script src="{{ static_url("js/utils.js") }}" type="text/javascript" charset="utf-8"></script>
202 <script src="{{ static_url("js/utils.js") }}" type="text/javascript" charset="utf-8"></script>
203 <script src="{{ static_url("js/layoutmanager.js") }}" type="text/javascript" charset="utf-8"></script>
203 <script src="{{ static_url("js/layoutmanager.js") }}" type="text/javascript" charset="utf-8"></script>
204 <script src="{{ static_url("js/mathjaxutils.js") }}" type="text/javascript" charset="utf-8"></script>
204 <script src="{{ static_url("js/mathjaxutils.js") }}" type="text/javascript" charset="utf-8"></script>
205 <script src="{{ static_url("js/outputarea.js") }}" type="text/javascript" charset="utf-8"></script>
205 <script src="{{ static_url("js/outputarea.js") }}" type="text/javascript" charset="utf-8"></script>
206 <script src="{{ static_url("js/cell.js") }}" type="text/javascript" charset="utf-8"></script>
206 <script src="{{ static_url("js/cell.js") }}" type="text/javascript" charset="utf-8"></script>
207 <script src="{{ static_url("js/codecell.js") }}" type="text/javascript" charset="utf-8"></script>
207 <script src="{{ static_url("js/codecell.js") }}" type="text/javascript" charset="utf-8"></script>
208 <script src="{{ static_url("js/completer.js") }}" type="text/javascript" charset="utf-8"></script>
208 <script src="{{ static_url("js/completer.js") }}" type="text/javascript" charset="utf-8"></script>
209 <script src="{{ static_url("js/textcell.js") }}" type="text/javascript" charset="utf-8"></script>
209 <script src="{{ static_url("js/textcell.js") }}" type="text/javascript" charset="utf-8"></script>
210 <script src="{{ static_url("js/kernel.js") }}" type="text/javascript" charset="utf-8"></script>
210 <script src="{{ static_url("js/kernel.js") }}" type="text/javascript" charset="utf-8"></script>
211 <script src="{{ static_url("js/savewidget.js") }}" type="text/javascript" charset="utf-8"></script>
211 <script src="{{ static_url("js/savewidget.js") }}" type="text/javascript" charset="utf-8"></script>
212 <script src="{{ static_url("js/quickhelp.js") }}" type="text/javascript" charset="utf-8"></script>
212 <script src="{{ static_url("js/quickhelp.js") }}" type="text/javascript" charset="utf-8"></script>
213 <script src="{{ static_url("js/pager.js") }}" type="text/javascript" charset="utf-8"></script>
213 <script src="{{ static_url("js/pager.js") }}" type="text/javascript" charset="utf-8"></script>
214 <script src="{{ static_url("js/menubar.js") }}" type="text/javascript" charset="utf-8"></script>
214 <script src="{{ static_url("js/menubar.js") }}" type="text/javascript" charset="utf-8"></script>
215 <script src="{{ static_url("js/toolbar.js") }}" type="text/javascript" charset="utf-8"></script>
215 <script src="{{ static_url("js/toolbar.js") }}" type="text/javascript" charset="utf-8"></script>
216 <script src="{{ static_url("js/maintoolbar.js") }}" type="text/javascript" charset="utf-8"></script>
216 <script src="{{ static_url("js/maintoolbar.js") }}" type="text/javascript" charset="utf-8"></script>
217 <script src="{{ static_url("js/notebook.js") }}" type="text/javascript" charset="utf-8"></script>
217 <script src="{{ static_url("js/notebook.js") }}" type="text/javascript" charset="utf-8"></script>
218 <script src="{{ static_url("js/notificationwidget.js") }}" type="text/javascript" charset="utf-8"></script>
218 <script src="{{ static_url("js/notificationwidget.js") }}" type="text/javascript" charset="utf-8"></script>
219 <script src="{{ static_url("js/notificationarea.js") }}" type="text/javascript" charset="utf-8"></script>
219 <script src="{{ static_url("js/notificationarea.js") }}" type="text/javascript" charset="utf-8"></script>
220 <script src="{{ static_url("js/tooltip.js") }}" type="text/javascript" charset="utf-8"></script>
220 <script src="{{ static_url("js/tooltip.js") }}" type="text/javascript" charset="utf-8"></script>
221 <script src="{{ static_url("js/config.js") }}" type="text/javascript" charset="utf-8"></script>
221 <script src="{{ static_url("js/config.js") }}" type="text/javascript" charset="utf-8"></script>
222 <script src="{{ static_url("js/notebookmain.js") }}" type="text/javascript" charset="utf-8"></script>
222 <script src="{{ static_url("js/notebookmain.js") }}" type="text/javascript" charset="utf-8"></script>
223
223
224 <script src="{{ static_url("js/contexthint.js") }}" charset="utf-8"></script>
224 <script src="{{ static_url("js/contexthint.js") }}" charset="utf-8"></script>
225
225
226 {% end %}
226 {% end %}
General Comments 0
You need to be logged in to leave comments. Login now