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