##// END OF EJS Templates
review pass on multidir js
MinRK -
Show More
@@ -1,294 +1,298 b''
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008-2011 The IPython Development Team
2 // Copyright (C) 2008-2011 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // MenuBar
9 // MenuBar
10 //============================================================================
10 //============================================================================
11
11
12 /**
12 /**
13 * @module IPython
13 * @module IPython
14 * @namespace IPython
14 * @namespace IPython
15 * @submodule MenuBar
15 * @submodule MenuBar
16 */
16 */
17
17
18
18
19 var IPython = (function (IPython) {
19 var IPython = (function (IPython) {
20 "use strict";
20 "use strict";
21
21
22 var utils = IPython.utils;
22 var utils = IPython.utils;
23
23
24 /**
24 /**
25 * A MenuBar Class to generate the menubar of IPython notebook
25 * A MenuBar Class to generate the menubar of IPython notebook
26 * @Class MenuBar
26 * @Class MenuBar
27 *
27 *
28 * @constructor
28 * @constructor
29 *
29 *
30 *
30 *
31 * @param selector {string} selector for the menubar element in DOM
31 * @param selector {string} selector for the menubar element in DOM
32 * @param {object} [options]
32 * @param {object} [options]
33 * @param [options.baseProjectUrl] {String} String to use for the
33 * @param [options.baseProjectUrl] {String} String to use for the
34 * Base Project url, default would be to inspect
34 * Base Project url, default would be to inspect
35 * $('body').data('baseProjectUrl');
35 * $('body').data('baseProjectUrl');
36 * does not support change for now is set through this option
36 * does not support change for now is set through this option
37 */
37 */
38 var MenuBar = function (selector, options) {
38 var MenuBar = function (selector, options) {
39 var options = options || {};
39 options = options || {};
40 if(options.baseProjectUrl!= undefined){
40 if (options.baseProjectUrl !== undefined) {
41 this._baseProjectUrl = options.baseProjectUrl;
41 this._baseProjectUrl = options.baseProjectUrl;
42 }
42 }
43 this.selector = selector;
43 this.selector = selector;
44 if (this.selector !== undefined) {
44 if (this.selector !== undefined) {
45 this.element = $(selector);
45 this.element = $(selector);
46 this.style();
46 this.style();
47 this.bind_events();
47 this.bind_events();
48 }
48 }
49 };
49 };
50
50
51 MenuBar.prototype.baseProjectUrl = function(){
51 MenuBar.prototype.baseProjectUrl = function(){
52 return this._baseProjectUrl || $('body').data('baseProjectUrl');
52 return this._baseProjectUrl || $('body').data('baseProjectUrl');
53 };
53 };
54
54
55 MenuBar.prototype.notebookPath = function() {
55 MenuBar.prototype.notebookPath = function() {
56 var path = $('body').data('notebookPath');
56 var path = $('body').data('notebookPath');
57 path = decodeURIComponent(path);
57 path = decodeURIComponent(path);
58 return path
58 return path;
59 };
59 };
60
60
61 MenuBar.prototype.style = function () {
61 MenuBar.prototype.style = function () {
62 this.element.addClass('border-box-sizing');
62 this.element.addClass('border-box-sizing');
63 this.element.find("li").click(function (event, ui) {
63 this.element.find("li").click(function (event, ui) {
64 // The selected cell loses focus when the menu is entered, so we
64 // The selected cell loses focus when the menu is entered, so we
65 // re-select it upon selection.
65 // re-select it upon selection.
66 var i = IPython.notebook.get_selected_index();
66 var i = IPython.notebook.get_selected_index();
67 IPython.notebook.select(i);
67 IPython.notebook.select(i);
68 }
68 }
69 );
69 );
70 };
70 };
71
71
72
72
73 MenuBar.prototype.bind_events = function () {
73 MenuBar.prototype.bind_events = function () {
74 // File
74 // File
75 var that = this;
75 var that = this;
76 this.element.find('#new_notebook').click(function () {
76 this.element.find('#new_notebook').click(function () {
77 IPython.notebook.new_notebook();
77 IPython.notebook.new_notebook();
78 });
78 });
79 this.element.find('#open_notebook').click(function () {
79 this.element.find('#open_notebook').click(function () {
80 window.open(that.baseProjectUrl() + 'tree' + that.notebookPath());
80 window.open(utils.url_path_join(
81 that.baseProjectUrl(),
82 'tree',
83 that.notebookPath()
84 ));
81 });
85 });
82 this.element.find('#copy_notebook').click(function () {
86 this.element.find('#copy_notebook').click(function () {
83 IPython.notebook.copy_notebook();
87 IPython.notebook.copy_notebook();
84 return false;
88 return false;
85 });
89 });
86 this.element.find('#download_ipynb').click(function () {
90 this.element.find('#download_ipynb').click(function () {
87 var notebook_name = IPython.notebook.get_notebook_name();
91 var notebook_name = IPython.notebook.get_notebook_name();
88 if (IPython.notebook.dirty) {
92 if (IPython.notebook.dirty) {
89 IPython.notebook.save_notebook({async : false});
93 IPython.notebook.save_notebook({async : false});
90 }
94 }
91
95
92 var url = utils.url_path_join(
96 var url = utils.url_path_join(
93 that.baseProjectUrl(),
97 that.baseProjectUrl(),
94 'api/notebooks',
98 'api/notebooks',
95 that.notebookPath(),
99 that.notebookPath(),
96 notebook_name + '.ipynb?format=json&download=True'
100 notebook_name + '.ipynb?format=json&download=True'
97 );
101 );
98 window.location.assign(url);
102 window.location.assign(url);
99 });
103 });
100 this.element.find('#download_py').click(function () {
104 this.element.find('#download_py').click(function () {
101 var notebook_name = IPython.notebook.get_notebook_name();
105 var notebook_name = IPython.notebook.get_notebook_name();
102 if (IPython.notebook.dirty) {
106 if (IPython.notebook.dirty) {
103 IPython.notebook.save_notebook({async : false});
107 IPython.notebook.save_notebook({async : false});
104 }
108 }
105 var url = utils.url_path_join(
109 var url = utils.url_path_join(
106 that.baseProjectUrl(),
110 that.baseProjectUrl(),
107 'api/notebooks',
111 'api/notebooks',
108 that.notebookPath(),
112 that.notebookPath(),
109 notebook_name + '.ipynb?format=py&download=True'
113 notebook_name + '.ipynb?format=py&download=True'
110 );
114 );
111 window.location.assign(url);
115 window.location.assign(url);
112 });
116 });
113 this.element.find('#rename_notebook').click(function () {
117 this.element.find('#rename_notebook').click(function () {
114 IPython.save_widget.rename_notebook();
118 IPython.save_widget.rename_notebook();
115 });
119 });
116 this.element.find('#save_checkpoint').click(function () {
120 this.element.find('#save_checkpoint').click(function () {
117 IPython.notebook.save_checkpoint();
121 IPython.notebook.save_checkpoint();
118 });
122 });
119 this.element.find('#restore_checkpoint').click(function () {
123 this.element.find('#restore_checkpoint').click(function () {
120 });
124 });
121 this.element.find('#kill_and_exit').click(function () {
125 this.element.find('#kill_and_exit').click(function () {
122 IPython.notebook.session.delete_session();
126 IPython.notebook.session.delete_session();
123 setTimeout(function(){window.close();}, 500);
127 setTimeout(function(){window.close();}, 500);
124 });
128 });
125 // Edit
129 // Edit
126 this.element.find('#cut_cell').click(function () {
130 this.element.find('#cut_cell').click(function () {
127 IPython.notebook.cut_cell();
131 IPython.notebook.cut_cell();
128 });
132 });
129 this.element.find('#copy_cell').click(function () {
133 this.element.find('#copy_cell').click(function () {
130 IPython.notebook.copy_cell();
134 IPython.notebook.copy_cell();
131 });
135 });
132 this.element.find('#delete_cell').click(function () {
136 this.element.find('#delete_cell').click(function () {
133 IPython.notebook.delete_cell();
137 IPython.notebook.delete_cell();
134 });
138 });
135 this.element.find('#undelete_cell').click(function () {
139 this.element.find('#undelete_cell').click(function () {
136 IPython.notebook.undelete();
140 IPython.notebook.undelete();
137 });
141 });
138 this.element.find('#split_cell').click(function () {
142 this.element.find('#split_cell').click(function () {
139 IPython.notebook.split_cell();
143 IPython.notebook.split_cell();
140 });
144 });
141 this.element.find('#merge_cell_above').click(function () {
145 this.element.find('#merge_cell_above').click(function () {
142 IPython.notebook.merge_cell_above();
146 IPython.notebook.merge_cell_above();
143 });
147 });
144 this.element.find('#merge_cell_below').click(function () {
148 this.element.find('#merge_cell_below').click(function () {
145 IPython.notebook.merge_cell_below();
149 IPython.notebook.merge_cell_below();
146 });
150 });
147 this.element.find('#move_cell_up').click(function () {
151 this.element.find('#move_cell_up').click(function () {
148 IPython.notebook.move_cell_up();
152 IPython.notebook.move_cell_up();
149 });
153 });
150 this.element.find('#move_cell_down').click(function () {
154 this.element.find('#move_cell_down').click(function () {
151 IPython.notebook.move_cell_down();
155 IPython.notebook.move_cell_down();
152 });
156 });
153 this.element.find('#select_previous').click(function () {
157 this.element.find('#select_previous').click(function () {
154 IPython.notebook.select_prev();
158 IPython.notebook.select_prev();
155 });
159 });
156 this.element.find('#select_next').click(function () {
160 this.element.find('#select_next').click(function () {
157 IPython.notebook.select_next();
161 IPython.notebook.select_next();
158 });
162 });
159 this.element.find('#edit_nb_metadata').click(function () {
163 this.element.find('#edit_nb_metadata').click(function () {
160 IPython.notebook.edit_metadata();
164 IPython.notebook.edit_metadata();
161 });
165 });
162
166
163 // View
167 // View
164 this.element.find('#toggle_header').click(function () {
168 this.element.find('#toggle_header').click(function () {
165 $('div#header').toggle();
169 $('div#header').toggle();
166 IPython.layout_manager.do_resize();
170 IPython.layout_manager.do_resize();
167 });
171 });
168 this.element.find('#toggle_toolbar').click(function () {
172 this.element.find('#toggle_toolbar').click(function () {
169 $('div#maintoolbar').toggle();
173 $('div#maintoolbar').toggle();
170 IPython.layout_manager.do_resize();
174 IPython.layout_manager.do_resize();
171 });
175 });
172 // Insert
176 // Insert
173 this.element.find('#insert_cell_above').click(function () {
177 this.element.find('#insert_cell_above').click(function () {
174 IPython.notebook.insert_cell_above('code');
178 IPython.notebook.insert_cell_above('code');
175 });
179 });
176 this.element.find('#insert_cell_below').click(function () {
180 this.element.find('#insert_cell_below').click(function () {
177 IPython.notebook.insert_cell_below('code');
181 IPython.notebook.insert_cell_below('code');
178 });
182 });
179 // Cell
183 // Cell
180 this.element.find('#run_cell').click(function () {
184 this.element.find('#run_cell').click(function () {
181 IPython.notebook.execute_selected_cell();
185 IPython.notebook.execute_selected_cell();
182 });
186 });
183 this.element.find('#run_cell_in_place').click(function () {
187 this.element.find('#run_cell_in_place').click(function () {
184 IPython.notebook.execute_selected_cell({terminal:true});
188 IPython.notebook.execute_selected_cell({terminal:true});
185 });
189 });
186 this.element.find('#run_all_cells').click(function () {
190 this.element.find('#run_all_cells').click(function () {
187 IPython.notebook.execute_all_cells();
191 IPython.notebook.execute_all_cells();
188 }).attr('title', 'Run all cells in the notebook');
192 }).attr('title', 'Run all cells in the notebook');
189 this.element.find('#run_all_cells_above').click(function () {
193 this.element.find('#run_all_cells_above').click(function () {
190 IPython.notebook.execute_cells_above();
194 IPython.notebook.execute_cells_above();
191 }).attr('title', 'Run all cells above (but not including) this cell');
195 }).attr('title', 'Run all cells above (but not including) this cell');
192 this.element.find('#run_all_cells_below').click(function () {
196 this.element.find('#run_all_cells_below').click(function () {
193 IPython.notebook.execute_cells_below();
197 IPython.notebook.execute_cells_below();
194 }).attr('title', 'Run this cell and all cells below it');
198 }).attr('title', 'Run this cell and all cells below it');
195 this.element.find('#to_code').click(function () {
199 this.element.find('#to_code').click(function () {
196 IPython.notebook.to_code();
200 IPython.notebook.to_code();
197 });
201 });
198 this.element.find('#to_markdown').click(function () {
202 this.element.find('#to_markdown').click(function () {
199 IPython.notebook.to_markdown();
203 IPython.notebook.to_markdown();
200 });
204 });
201 this.element.find('#to_raw').click(function () {
205 this.element.find('#to_raw').click(function () {
202 IPython.notebook.to_raw();
206 IPython.notebook.to_raw();
203 });
207 });
204 this.element.find('#to_heading1').click(function () {
208 this.element.find('#to_heading1').click(function () {
205 IPython.notebook.to_heading(undefined, 1);
209 IPython.notebook.to_heading(undefined, 1);
206 });
210 });
207 this.element.find('#to_heading2').click(function () {
211 this.element.find('#to_heading2').click(function () {
208 IPython.notebook.to_heading(undefined, 2);
212 IPython.notebook.to_heading(undefined, 2);
209 });
213 });
210 this.element.find('#to_heading3').click(function () {
214 this.element.find('#to_heading3').click(function () {
211 IPython.notebook.to_heading(undefined, 3);
215 IPython.notebook.to_heading(undefined, 3);
212 });
216 });
213 this.element.find('#to_heading4').click(function () {
217 this.element.find('#to_heading4').click(function () {
214 IPython.notebook.to_heading(undefined, 4);
218 IPython.notebook.to_heading(undefined, 4);
215 });
219 });
216 this.element.find('#to_heading5').click(function () {
220 this.element.find('#to_heading5').click(function () {
217 IPython.notebook.to_heading(undefined, 5);
221 IPython.notebook.to_heading(undefined, 5);
218 });
222 });
219 this.element.find('#to_heading6').click(function () {
223 this.element.find('#to_heading6').click(function () {
220 IPython.notebook.to_heading(undefined, 6);
224 IPython.notebook.to_heading(undefined, 6);
221 });
225 });
222 this.element.find('#toggle_output').click(function () {
226 this.element.find('#toggle_output').click(function () {
223 IPython.notebook.toggle_output();
227 IPython.notebook.toggle_output();
224 });
228 });
225 this.element.find('#collapse_all_output').click(function () {
229 this.element.find('#collapse_all_output').click(function () {
226 IPython.notebook.collapse_all_output();
230 IPython.notebook.collapse_all_output();
227 });
231 });
228 this.element.find('#scroll_all_output').click(function () {
232 this.element.find('#scroll_all_output').click(function () {
229 IPython.notebook.scroll_all_output();
233 IPython.notebook.scroll_all_output();
230 });
234 });
231 this.element.find('#expand_all_output').click(function () {
235 this.element.find('#expand_all_output').click(function () {
232 IPython.notebook.expand_all_output();
236 IPython.notebook.expand_all_output();
233 });
237 });
234 this.element.find('#clear_all_output').click(function () {
238 this.element.find('#clear_all_output').click(function () {
235 IPython.notebook.clear_all_output();
239 IPython.notebook.clear_all_output();
236 });
240 });
237 // Kernel
241 // Kernel
238 this.element.find('#int_kernel').click(function () {
242 this.element.find('#int_kernel').click(function () {
239 IPython.notebook.session.interrupt_kernel();
243 IPython.notebook.session.interrupt_kernel();
240 });
244 });
241 this.element.find('#restart_kernel').click(function () {
245 this.element.find('#restart_kernel').click(function () {
242 IPython.notebook.restart_kernel();
246 IPython.notebook.restart_kernel();
243 });
247 });
244 // Help
248 // Help
245 this.element.find('#keyboard_shortcuts').click(function () {
249 this.element.find('#keyboard_shortcuts').click(function () {
246 IPython.quick_help.show_keyboard_shortcuts();
250 IPython.quick_help.show_keyboard_shortcuts();
247 });
251 });
248
252
249 this.update_restore_checkpoint(null);
253 this.update_restore_checkpoint(null);
250
254
251 $([IPython.events]).on('checkpoints_listed.Notebook', function (event, data) {
255 $([IPython.events]).on('checkpoints_listed.Notebook', function (event, data) {
252 that.update_restore_checkpoint(IPython.notebook.checkpoints);
256 that.update_restore_checkpoint(IPython.notebook.checkpoints);
253 });
257 });
254
258
255 $([IPython.events]).on('checkpoint_created.Notebook', function (event, data) {
259 $([IPython.events]).on('checkpoint_created.Notebook', function (event, data) {
256 that.update_restore_checkpoint(IPython.notebook.checkpoints);
260 that.update_restore_checkpoint(IPython.notebook.checkpoints);
257 });
261 });
258 };
262 };
259
263
260 MenuBar.prototype.update_restore_checkpoint = function(checkpoints) {
264 MenuBar.prototype.update_restore_checkpoint = function(checkpoints) {
261 var ul = this.element.find("#restore_checkpoint").find("ul");
265 var ul = this.element.find("#restore_checkpoint").find("ul");
262 ul.empty();
266 ul.empty();
263 if (! checkpoints || checkpoints.length == 0) {
267 if (!checkpoints || checkpoints.length === 0) {
264 ul.append(
268 ul.append(
265 $("<li/>")
269 $("<li/>")
266 .addClass("disabled")
270 .addClass("disabled")
267 .append(
271 .append(
268 $("<a/>")
272 $("<a/>")
269 .text("No checkpoints")
273 .text("No checkpoints")
270 )
274 )
271 );
275 );
272 return;
276 return;
273 };
277 }
274
278
275 checkpoints.map(function (checkpoint) {
279 checkpoints.map(function (checkpoint) {
276 var d = new Date(checkpoint.last_modified);
280 var d = new Date(checkpoint.last_modified);
277 ul.append(
281 ul.append(
278 $("<li/>").append(
282 $("<li/>").append(
279 $("<a/>")
283 $("<a/>")
280 .attr("href", "#")
284 .attr("href", "#")
281 .text(d.format("mmm dd HH:MM:ss"))
285 .text(d.format("mmm dd HH:MM:ss"))
282 .click(function () {
286 .click(function () {
283 IPython.notebook.restore_checkpoint_dialog(checkpoint);
287 IPython.notebook.restore_checkpoint_dialog(checkpoint);
284 })
288 })
285 )
289 )
286 );
290 );
287 });
291 });
288 };
292 };
289
293
290 IPython.MenuBar = MenuBar;
294 IPython.MenuBar = MenuBar;
291
295
292 return IPython;
296 return IPython;
293
297
294 }(IPython));
298 }(IPython));
@@ -1,169 +1,173 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 // SaveWidget
9 // SaveWidget
10 //============================================================================
10 //============================================================================
11
11
12 var IPython = (function (IPython) {
12 var IPython = (function (IPython) {
13 "use strict";
13 "use strict";
14
14
15 var utils = IPython.utils;
15 var utils = IPython.utils;
16
16
17 var SaveWidget = function (selector) {
17 var SaveWidget = function (selector) {
18 this.selector = selector;
18 this.selector = selector;
19 if (this.selector !== undefined) {
19 if (this.selector !== undefined) {
20 this.element = $(selector);
20 this.element = $(selector);
21 this.style();
21 this.style();
22 this.bind_events();
22 this.bind_events();
23 }
23 }
24 };
24 };
25
25
26
26
27 SaveWidget.prototype.style = function () {
27 SaveWidget.prototype.style = function () {
28 };
28 };
29
29
30
30
31 SaveWidget.prototype.bind_events = function () {
31 SaveWidget.prototype.bind_events = function () {
32 var that = this;
32 var that = this;
33 this.element.find('span#notebook_name').click(function () {
33 this.element.find('span#notebook_name').click(function () {
34 that.rename_notebook();
34 that.rename_notebook();
35 });
35 });
36 this.element.find('span#notebook_name').hover(function () {
36 this.element.find('span#notebook_name').hover(function () {
37 $(this).addClass("ui-state-hover");
37 $(this).addClass("ui-state-hover");
38 }, function () {
38 }, function () {
39 $(this).removeClass("ui-state-hover");
39 $(this).removeClass("ui-state-hover");
40 });
40 });
41 $([IPython.events]).on('notebook_loaded.Notebook', function () {
41 $([IPython.events]).on('notebook_loaded.Notebook', function () {
42 that.update_notebook_name();
42 that.update_notebook_name();
43 that.update_document_title();
43 that.update_document_title();
44 });
44 });
45 $([IPython.events]).on('notebook_saved.Notebook', function () {
45 $([IPython.events]).on('notebook_saved.Notebook', function () {
46 that.update_notebook_name();
46 that.update_notebook_name();
47 that.update_document_title();
47 that.update_document_title();
48 });
48 });
49 $([IPython.events]).on('notebook_renamed.Notebook', function () {
49 $([IPython.events]).on('notebook_renamed.Notebook', function () {
50 that.update_notebook_name();
50 that.update_notebook_name();
51 that.update_document_title();
51 that.update_document_title();
52 that.update_address_bar();
52 that.update_address_bar();
53 });
53 });
54 $([IPython.events]).on('notebook_save_failed.Notebook', function () {
54 $([IPython.events]).on('notebook_save_failed.Notebook', function () {
55 that.set_save_status('Autosave Failed!');
55 that.set_save_status('Autosave Failed!');
56 });
56 });
57 $([IPython.events]).on('checkpoints_listed.Notebook', function (event, data) {
57 $([IPython.events]).on('checkpoints_listed.Notebook', function (event, data) {
58 that.set_last_checkpoint(data[0]);
58 that.set_last_checkpoint(data[0]);
59 });
59 });
60
60
61 $([IPython.events]).on('checkpoint_created.Notebook', function (event, data) {
61 $([IPython.events]).on('checkpoint_created.Notebook', function (event, data) {
62 that.set_last_checkpoint(data);
62 that.set_last_checkpoint(data);
63 });
63 });
64 $([IPython.events]).on('set_dirty.Notebook', function (event, data) {
64 $([IPython.events]).on('set_dirty.Notebook', function (event, data) {
65 that.set_autosaved(data.value);
65 that.set_autosaved(data.value);
66 });
66 });
67 };
67 };
68
68
69
69
70 SaveWidget.prototype.rename_notebook = function () {
70 SaveWidget.prototype.rename_notebook = function () {
71 var that = this;
71 var that = this;
72 var dialog = $('<div/>').append(
72 var dialog = $('<div/>').append(
73 $("<p/>").addClass("rename-message")
73 $("<p/>").addClass("rename-message")
74 .html('Enter a new notebook name:')
74 .html('Enter a new notebook name:')
75 ).append(
75 ).append(
76 $("<br/>")
76 $("<br/>")
77 ).append(
77 ).append(
78 $('<input/>').attr('type','text').attr('size','25')
78 $('<input/>').attr('type','text').attr('size','25')
79 .val(IPython.notebook.get_notebook_name())
79 .val(IPython.notebook.get_notebook_name())
80 );
80 );
81 IPython.dialog.modal({
81 IPython.dialog.modal({
82 title: "Rename Notebook",
82 title: "Rename Notebook",
83 body: dialog,
83 body: dialog,
84 buttons : {
84 buttons : {
85 "Cancel": {},
85 "Cancel": {},
86 "OK": {
86 "OK": {
87 class: "btn-primary",
87 class: "btn-primary",
88 click: function () {
88 click: function () {
89 var new_name = $(this).find('input').val();
89 var new_name = $(this).find('input').val();
90 if (!IPython.notebook.test_notebook_name(new_name)) {
90 if (!IPython.notebook.test_notebook_name(new_name)) {
91 $(this).find('.rename-message').html(
91 $(this).find('.rename-message').html(
92 "Invalid notebook name. Notebook names must "+
92 "Invalid notebook name. Notebook names must "+
93 "have 1 or more characters and can contain any characters " +
93 "have 1 or more characters and can contain any characters " +
94 "except :/\\. Please enter a new notebook name:"
94 "except :/\\. Please enter a new notebook name:"
95 );
95 );
96 return false;
96 return false;
97 } else {
97 } else {
98 IPython.notebook.notebook_rename(new_name);
98 IPython.notebook.notebook_rename(new_name);
99 }
99 }
100 }}
100 }}
101 },
101 },
102 open : function (event, ui) {
102 open : function (event, ui) {
103 var that = $(this);
103 var that = $(this);
104 // Upon ENTER, click the OK button.
104 // Upon ENTER, click the OK button.
105 that.find('input[type="text"]').keydown(function (event, ui) {
105 that.find('input[type="text"]').keydown(function (event, ui) {
106 if (event.which === utils.keycodes.ENTER) {
106 if (event.which === utils.keycodes.ENTER) {
107 that.find('.btn-primary').first().click();
107 that.find('.btn-primary').first().click();
108 return false;
108 return false;
109 }
109 }
110 });
110 });
111 that.find('input[type="text"]').focus().select();
111 that.find('input[type="text"]').focus().select();
112 }
112 }
113 });
113 });
114 }
114 }
115
115
116
116
117 SaveWidget.prototype.update_notebook_name = function () {
117 SaveWidget.prototype.update_notebook_name = function () {
118 var nbname = IPython.notebook.get_notebook_name();
118 var nbname = IPython.notebook.get_notebook_name();
119 this.element.find('span#notebook_name').html(nbname);
119 this.element.find('span#notebook_name').html(nbname);
120 };
120 };
121
121
122
122
123 SaveWidget.prototype.update_document_title = function () {
123 SaveWidget.prototype.update_document_title = function () {
124 var nbname = IPython.notebook.get_notebook_name();
124 var nbname = IPython.notebook.get_notebook_name();
125 document.title = nbname;
125 document.title = nbname;
126 };
126 };
127
127
128 SaveWidget.prototype.update_address_bar = function(){
128 SaveWidget.prototype.update_address_bar = function(){
129 var nbname = IPython.notebook.notebook_name;
129 var nbname = IPython.notebook.notebook_name;
130 var path = IPython.notebook.notebookPath();
130 var path = IPython.notebook.notebookPath();
131 var state = {"path": path+nbname}
131 var state = {path : utils.url_path_join(path,nbname)};
132 window.history.replaceState(state, "", "/notebooks" + path+nbname);
132 window.history.replaceState(state, "", utils.url_path_join(
133 "/notebooks",
134 path,
135 nbname)
136 );
133 }
137 }
134
138
135
139
136 SaveWidget.prototype.set_save_status = function (msg) {
140 SaveWidget.prototype.set_save_status = function (msg) {
137 this.element.find('span#autosave_status').html(msg);
141 this.element.find('span#autosave_status').html(msg);
138 }
142 }
139
143
140 SaveWidget.prototype.set_checkpoint_status = function (msg) {
144 SaveWidget.prototype.set_checkpoint_status = function (msg) {
141 this.element.find('span#checkpoint_status').html(msg);
145 this.element.find('span#checkpoint_status').html(msg);
142 }
146 }
143
147
144 SaveWidget.prototype.set_last_checkpoint = function (checkpoint) {
148 SaveWidget.prototype.set_last_checkpoint = function (checkpoint) {
145 if (!checkpoint) {
149 if (!checkpoint) {
146 this.set_checkpoint_status("");
150 this.set_checkpoint_status("");
147 return;
151 return;
148 }
152 }
149 var d = new Date(checkpoint.last_modified);
153 var d = new Date(checkpoint.last_modified);
150 this.set_checkpoint_status(
154 this.set_checkpoint_status(
151 "Last Checkpoint: " + d.format('mmm dd HH:MM')
155 "Last Checkpoint: " + d.format('mmm dd HH:MM')
152 );
156 );
153 }
157 }
154
158
155 SaveWidget.prototype.set_autosaved = function (dirty) {
159 SaveWidget.prototype.set_autosaved = function (dirty) {
156 if (dirty) {
160 if (dirty) {
157 this.set_save_status("(unsaved changes)");
161 this.set_save_status("(unsaved changes)");
158 } else {
162 } else {
159 this.set_save_status("(autosaved)");
163 this.set_save_status("(autosaved)");
160 }
164 }
161 };
165 };
162
166
163
167
164 IPython.SaveWidget = SaveWidget;
168 IPython.SaveWidget = SaveWidget;
165
169
166 return IPython;
170 return IPython;
167
171
168 }(IPython));
172 }(IPython));
169
173
@@ -1,525 +1,523 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 // Kernel
9 // Kernel
10 //============================================================================
10 //============================================================================
11
11
12 /**
12 /**
13 * @module IPython
13 * @module IPython
14 * @namespace IPython
14 * @namespace IPython
15 * @submodule Kernel
15 * @submodule Kernel
16 */
16 */
17
17
18 var IPython = (function (IPython) {
18 var IPython = (function (IPython) {
19
19
20 var utils = IPython.utils;
20 var utils = IPython.utils;
21
21
22 // Initialization and connection.
22 // Initialization and connection.
23 /**
23 /**
24 * A Kernel Class to communicate with the Python kernel
24 * A Kernel Class to communicate with the Python kernel
25 * @Class Kernel
25 * @Class Kernel
26 */
26 */
27 var Kernel = function (base_url) {
27 var Kernel = function (base_url) {
28 this.kernel_id = null;
28 this.kernel_id = null;
29 this.shell_channel = null;
29 this.shell_channel = null;
30 this.iopub_channel = null;
30 this.iopub_channel = null;
31 this.stdin_channel = null;
31 this.stdin_channel = null;
32 this.base_url = base_url;
32 this.base_url = base_url;
33 this.running = false;
33 this.running = false;
34 this.username = "username";
34 this.username = "username";
35 this.session_id = utils.uuid();
35 this.session_id = utils.uuid();
36 this._msg_callbacks = {};
36 this._msg_callbacks = {};
37
37
38 if (typeof(WebSocket) !== 'undefined') {
38 if (typeof(WebSocket) !== 'undefined') {
39 this.WebSocket = WebSocket;
39 this.WebSocket = WebSocket;
40 } else if (typeof(MozWebSocket) !== 'undefined') {
40 } else if (typeof(MozWebSocket) !== 'undefined') {
41 this.WebSocket = MozWebSocket;
41 this.WebSocket = MozWebSocket;
42 } else {
42 } else {
43 alert('Your browser does not have WebSocket support, please try Chrome, Safari or Firefox β‰₯ 6. Firefox 4 and 5 are also supported by you have to enable WebSockets in about:config.');
43 alert('Your browser does not have WebSocket support, please try Chrome, Safari or Firefox β‰₯ 6. Firefox 4 and 5 are also supported by you have to enable WebSockets in about:config.');
44 };
44 };
45 this.bind_events();
45 this.bind_events();
46 };
46 };
47
47
48
48
49 Kernel.prototype._get_msg = function (msg_type, content) {
49 Kernel.prototype._get_msg = function (msg_type, content) {
50 var msg = {
50 var msg = {
51 header : {
51 header : {
52 msg_id : utils.uuid(),
52 msg_id : utils.uuid(),
53 username : this.username,
53 username : this.username,
54 session : this.session_id,
54 session : this.session_id,
55 msg_type : msg_type
55 msg_type : msg_type
56 },
56 },
57 metadata : {},
57 metadata : {},
58 content : content,
58 content : content,
59 parent_header : {}
59 parent_header : {}
60 };
60 };
61 return msg;
61 return msg;
62 };
62 };
63
63
64 Kernel.prototype.bind_events = function() {
64 Kernel.prototype.bind_events = function() {
65 var that = this;
65 var that = this;
66 $([IPython.events]).on('send_input_reply.Kernel', function(evt, data) {
66 $([IPython.events]).on('send_input_reply.Kernel', function(evt, data) {
67 that.send_input_reply(data);
67 that.send_input_reply(data);
68 });
68 });
69 }
69 }
70
70
71 /**
71 /**
72 * Start the Python kernel
72 * Start the Python kernel
73 * @method start
73 * @method start
74 */
74 */
75 Kernel.prototype.start = function (params) {
75 Kernel.prototype.start = function (params) {
76 var that = this;
76 params = params || {};
77 params = params || {};
77 if (!this.running) {
78 if (!this.running) {
78 var qs = $.param(params);
79 var qs = $.param(params);
79 var url = this.base_url + '?' + qs;
80 var url = this.base_url + '?' + qs;
80 $.post(url,
81 $.post(url,
81 $.proxy(this._kernel_started, this),
82 $.proxy(that._kernel_started,that),
82 'json'
83 'json'
83 );
84 );
84 };
85 };
85 };
86 };
87
86
88 /**
87 /**
89 * Restart the python kernel.
88 * Restart the python kernel.
90 *
89 *
91 * Emit a 'status_restarting.Kernel' event with
90 * Emit a 'status_restarting.Kernel' event with
92 * the current object as parameter
91 * the current object as parameter
93 *
92 *
94 * @method restart
93 * @method restart
95 */
94 */
96 Kernel.prototype.restart = function () {
95 Kernel.prototype.restart = function () {
97 $([IPython.events]).trigger('status_restarting.Kernel', {kernel: this});
96 $([IPython.events]).trigger('status_restarting.Kernel', {kernel: this});
98 var that = this;
99 if (this.running) {
97 if (this.running) {
100 this.stop_channels();
98 this.stop_channels();
101 var url = this.kernel_url + "/restart";
99 var url = utils.url_path_join(this.kernel_url, "restart");
102 $.post(url,
100 $.post(url,
103 $.proxy(that._kernel_started, that),
101 $.proxy(this._kernel_started, this),
104 'json'
102 'json'
105 );
103 );
106 };
104 };
107 };
105 };
108
106
109
107
110 Kernel.prototype._kernel_started = function (json) {
108 Kernel.prototype._kernel_started = function (json) {
111 console.log("Kernel started: ", json.id);
109 console.log("Kernel started: ", json.id);
112 this.running = true;
110 this.running = true;
113 this.kernel_id = json.id;
111 this.kernel_id = json.id;
114 var ws_url = json.ws_url;
112 var ws_url = json.ws_url;
115 if (ws_url.match(/wss?:\/\//) == null) {
113 if (ws_url.match(/wss?:\/\//) == null) {
116 // trailing 's' in https will become wss for secure web sockets
114 // trailing 's' in https will become wss for secure web sockets
117 prot = location.protocol.replace('http', 'ws') + "//";
115 prot = location.protocol.replace('http', 'ws') + "//";
118 ws_url = prot + location.host + ws_url;
116 ws_url = prot + location.host + ws_url;
119 };
117 };
120 this.ws_url = ws_url;
118 this.ws_url = ws_url;
121 this.kernel_url = this.base_url + "/" + this.kernel_id;
119 this.kernel_url = utils.url_path_join(this.base_url, this.kernel_id);
122 this.start_channels();
120 this.start_channels();
123 };
121 };
124
122
125
123
126 Kernel.prototype._websocket_closed = function(ws_url, early) {
124 Kernel.prototype._websocket_closed = function(ws_url, early) {
127 this.stop_channels();
125 this.stop_channels();
128 $([IPython.events]).trigger('websocket_closed.Kernel',
126 $([IPython.events]).trigger('websocket_closed.Kernel',
129 {ws_url: ws_url, kernel: this, early: early}
127 {ws_url: ws_url, kernel: this, early: early}
130 );
128 );
131 };
129 };
132
130
133 /**
131 /**
134 * Start the `shell`and `iopub` channels.
132 * Start the `shell`and `iopub` channels.
135 * Will stop and restart them if they already exist.
133 * Will stop and restart them if they already exist.
136 *
134 *
137 * @method start_channels
135 * @method start_channels
138 */
136 */
139 Kernel.prototype.start_channels = function () {
137 Kernel.prototype.start_channels = function () {
140 var that = this;
138 var that = this;
141 this.stop_channels();
139 this.stop_channels();
142 var ws_url = this.ws_url + this.kernel_url;
140 var ws_url = this.ws_url + this.kernel_url;
143 console.log("Starting WebSockets:", ws_url);
141 console.log("Starting WebSockets:", ws_url);
144 this.shell_channel = new this.WebSocket(ws_url + "/shell");
142 this.shell_channel = new this.WebSocket(ws_url + "/shell");
145 this.stdin_channel = new this.WebSocket(ws_url + "/stdin");
143 this.stdin_channel = new this.WebSocket(ws_url + "/stdin");
146 this.iopub_channel = new this.WebSocket(ws_url + "/iopub");
144 this.iopub_channel = new this.WebSocket(ws_url + "/iopub");
147
145
148 var already_called_onclose = false; // only alert once
146 var already_called_onclose = false; // only alert once
149 var ws_closed_early = function(evt){
147 var ws_closed_early = function(evt){
150 if (already_called_onclose){
148 if (already_called_onclose){
151 return;
149 return;
152 }
150 }
153 already_called_onclose = true;
151 already_called_onclose = true;
154 if ( ! evt.wasClean ){
152 if ( ! evt.wasClean ){
155 that._websocket_closed(ws_url, true);
153 that._websocket_closed(ws_url, true);
156 }
154 }
157 };
155 };
158 var ws_closed_late = function(evt){
156 var ws_closed_late = function(evt){
159 if (already_called_onclose){
157 if (already_called_onclose){
160 return;
158 return;
161 }
159 }
162 already_called_onclose = true;
160 already_called_onclose = true;
163 if ( ! evt.wasClean ){
161 if ( ! evt.wasClean ){
164 that._websocket_closed(ws_url, false);
162 that._websocket_closed(ws_url, false);
165 }
163 }
166 };
164 };
167 var channels = [this.shell_channel, this.iopub_channel, this.stdin_channel];
165 var channels = [this.shell_channel, this.iopub_channel, this.stdin_channel];
168 for (var i=0; i < channels.length; i++) {
166 for (var i=0; i < channels.length; i++) {
169 channels[i].onopen = $.proxy(this._ws_opened, this);
167 channels[i].onopen = $.proxy(this._ws_opened, this);
170 channels[i].onclose = ws_closed_early;
168 channels[i].onclose = ws_closed_early;
171 }
169 }
172 // switch from early-close to late-close message after 1s
170 // switch from early-close to late-close message after 1s
173 setTimeout(function() {
171 setTimeout(function() {
174 for (var i=0; i < channels.length; i++) {
172 for (var i=0; i < channels.length; i++) {
175 if (channels[i] !== null) {
173 if (channels[i] !== null) {
176 channels[i].onclose = ws_closed_late;
174 channels[i].onclose = ws_closed_late;
177 }
175 }
178 }
176 }
179 }, 1000);
177 }, 1000);
180 this.shell_channel.onmessage = $.proxy(this._handle_shell_reply, this);
178 this.shell_channel.onmessage = $.proxy(this._handle_shell_reply, this);
181 this.iopub_channel.onmessage = $.proxy(this._handle_iopub_reply, this);
179 this.iopub_channel.onmessage = $.proxy(this._handle_iopub_reply, this);
182 this.stdin_channel.onmessage = $.proxy(this._handle_input_request, this);
180 this.stdin_channel.onmessage = $.proxy(this._handle_input_request, this);
183 };
181 };
184
182
185 /**
183 /**
186 * Handle a websocket entering the open state
184 * Handle a websocket entering the open state
187 * sends session and cookie authentication info as first message.
185 * sends session and cookie authentication info as first message.
188 * Once all sockets are open, signal the Kernel.status_started event.
186 * Once all sockets are open, signal the Kernel.status_started event.
189 * @method _ws_opened
187 * @method _ws_opened
190 */
188 */
191 Kernel.prototype._ws_opened = function (evt) {
189 Kernel.prototype._ws_opened = function (evt) {
192 // send the session id so the Session object Python-side
190 // send the session id so the Session object Python-side
193 // has the same identity
191 // has the same identity
194 evt.target.send(this.session_id + ':' + document.cookie);
192 evt.target.send(this.session_id + ':' + document.cookie);
195
193
196 var channels = [this.shell_channel, this.iopub_channel, this.stdin_channel];
194 var channels = [this.shell_channel, this.iopub_channel, this.stdin_channel];
197 for (var i=0; i < channels.length; i++) {
195 for (var i=0; i < channels.length; i++) {
198 // if any channel is not ready, don't trigger event.
196 // if any channel is not ready, don't trigger event.
199 if ( !channels[i].readyState ) return;
197 if ( !channels[i].readyState ) return;
200 }
198 }
201 // all events ready, trigger started event.
199 // all events ready, trigger started event.
202 $([IPython.events]).trigger('status_started.Kernel', {kernel: this});
200 $([IPython.events]).trigger('status_started.Kernel', {kernel: this});
203 };
201 };
204
202
205 /**
203 /**
206 * Stop the websocket channels.
204 * Stop the websocket channels.
207 * @method stop_channels
205 * @method stop_channels
208 */
206 */
209 Kernel.prototype.stop_channels = function () {
207 Kernel.prototype.stop_channels = function () {
210 var channels = [this.shell_channel, this.iopub_channel, this.stdin_channel];
208 var channels = [this.shell_channel, this.iopub_channel, this.stdin_channel];
211 for (var i=0; i < channels.length; i++) {
209 for (var i=0; i < channels.length; i++) {
212 if ( channels[i] !== null ) {
210 if ( channels[i] !== null ) {
213 channels[i].onclose = function (evt) {};
211 channels[i].onclose = function (evt) {};
214 channels[i].close();
212 channels[i].close();
215 }
213 }
216 };
214 };
217 this.shell_channel = this.iopub_channel = this.stdin_channel = null;
215 this.shell_channel = this.iopub_channel = this.stdin_channel = null;
218 };
216 };
219
217
220 // Main public methods.
218 // Main public methods.
221
219
222 /**
220 /**
223 * Get info on object asynchronoulsy
221 * Get info on object asynchronoulsy
224 *
222 *
225 * @async
223 * @async
226 * @param objname {string}
224 * @param objname {string}
227 * @param callback {dict}
225 * @param callback {dict}
228 * @method object_info_request
226 * @method object_info_request
229 *
227 *
230 * @example
228 * @example
231 *
229 *
232 * When calling this method pass a callbacks structure of the form:
230 * When calling this method pass a callbacks structure of the form:
233 *
231 *
234 * callbacks = {
232 * callbacks = {
235 * 'object_info_reply': object_info_reply_callback
233 * 'object_info_reply': object_info_reply_callback
236 * }
234 * }
237 *
235 *
238 * The `object_info_reply_callback` will be passed the content object of the
236 * The `object_info_reply_callback` will be passed the content object of the
239 *
237 *
240 * `object_into_reply` message documented in
238 * `object_into_reply` message documented in
241 * [IPython dev documentation](http://ipython.org/ipython-doc/dev/development/messaging.html#object-information)
239 * [IPython dev documentation](http://ipython.org/ipython-doc/dev/development/messaging.html#object-information)
242 */
240 */
243 Kernel.prototype.object_info_request = function (objname, callbacks) {
241 Kernel.prototype.object_info_request = function (objname, callbacks) {
244 if(typeof(objname)!=null && objname!=null)
242 if(typeof(objname)!=null && objname!=null)
245 {
243 {
246 var content = {
244 var content = {
247 oname : objname.toString(),
245 oname : objname.toString(),
248 detail_level : 0,
246 detail_level : 0,
249 };
247 };
250 var msg = this._get_msg("object_info_request", content);
248 var msg = this._get_msg("object_info_request", content);
251 this.shell_channel.send(JSON.stringify(msg));
249 this.shell_channel.send(JSON.stringify(msg));
252 this.set_callbacks_for_msg(msg.header.msg_id, callbacks);
250 this.set_callbacks_for_msg(msg.header.msg_id, callbacks);
253 return msg.header.msg_id;
251 return msg.header.msg_id;
254 }
252 }
255 return;
253 return;
256 }
254 }
257
255
258 /**
256 /**
259 * Execute given code into kernel, and pass result to callback.
257 * Execute given code into kernel, and pass result to callback.
260 *
258 *
261 * TODO: document input_request in callbacks
259 * TODO: document input_request in callbacks
262 *
260 *
263 * @async
261 * @async
264 * @method execute
262 * @method execute
265 * @param {string} code
263 * @param {string} code
266 * @param [callbacks] {Object} With the optional following keys
264 * @param [callbacks] {Object} With the optional following keys
267 * @param callbacks.'execute_reply' {function}
265 * @param callbacks.'execute_reply' {function}
268 * @param callbacks.'output' {function}
266 * @param callbacks.'output' {function}
269 * @param callbacks.'clear_output' {function}
267 * @param callbacks.'clear_output' {function}
270 * @param callbacks.'set_next_input' {function}
268 * @param callbacks.'set_next_input' {function}
271 * @param {object} [options]
269 * @param {object} [options]
272 * @param [options.silent=false] {Boolean}
270 * @param [options.silent=false] {Boolean}
273 * @param [options.user_expressions=empty_dict] {Dict}
271 * @param [options.user_expressions=empty_dict] {Dict}
274 * @param [options.user_variables=empty_list] {List od Strings}
272 * @param [options.user_variables=empty_list] {List od Strings}
275 * @param [options.allow_stdin=false] {Boolean} true|false
273 * @param [options.allow_stdin=false] {Boolean} true|false
276 *
274 *
277 * @example
275 * @example
278 *
276 *
279 * The options object should contain the options for the execute call. Its default
277 * The options object should contain the options for the execute call. Its default
280 * values are:
278 * values are:
281 *
279 *
282 * options = {
280 * options = {
283 * silent : true,
281 * silent : true,
284 * user_variables : [],
282 * user_variables : [],
285 * user_expressions : {},
283 * user_expressions : {},
286 * allow_stdin : false
284 * allow_stdin : false
287 * }
285 * }
288 *
286 *
289 * When calling this method pass a callbacks structure of the form:
287 * When calling this method pass a callbacks structure of the form:
290 *
288 *
291 * callbacks = {
289 * callbacks = {
292 * 'execute_reply': execute_reply_callback,
290 * 'execute_reply': execute_reply_callback,
293 * 'output': output_callback,
291 * 'output': output_callback,
294 * 'clear_output': clear_output_callback,
292 * 'clear_output': clear_output_callback,
295 * 'set_next_input': set_next_input_callback
293 * 'set_next_input': set_next_input_callback
296 * }
294 * }
297 *
295 *
298 * The `execute_reply_callback` will be passed the content and metadata
296 * The `execute_reply_callback` will be passed the content and metadata
299 * objects of the `execute_reply` message documented
297 * objects of the `execute_reply` message documented
300 * [here](http://ipython.org/ipython-doc/dev/development/messaging.html#execute)
298 * [here](http://ipython.org/ipython-doc/dev/development/messaging.html#execute)
301 *
299 *
302 * The `output_callback` will be passed `msg_type` ('stream','display_data','pyout','pyerr')
300 * The `output_callback` will be passed `msg_type` ('stream','display_data','pyout','pyerr')
303 * of the output and the content and metadata objects of the PUB/SUB channel that contains the
301 * of the output and the content and metadata objects of the PUB/SUB channel that contains the
304 * output:
302 * output:
305 *
303 *
306 * http://ipython.org/ipython-doc/dev/development/messaging.html#messages-on-the-pub-sub-socket
304 * http://ipython.org/ipython-doc/dev/development/messaging.html#messages-on-the-pub-sub-socket
307 *
305 *
308 * The `clear_output_callback` will be passed a content object that contains
306 * The `clear_output_callback` will be passed a content object that contains
309 * stdout, stderr and other fields that are booleans, as well as the metadata object.
307 * stdout, stderr and other fields that are booleans, as well as the metadata object.
310 *
308 *
311 * The `set_next_input_callback` will be passed the text that should become the next
309 * The `set_next_input_callback` will be passed the text that should become the next
312 * input cell.
310 * input cell.
313 */
311 */
314 Kernel.prototype.execute = function (code, callbacks, options) {
312 Kernel.prototype.execute = function (code, callbacks, options) {
315
313
316 var content = {
314 var content = {
317 code : code,
315 code : code,
318 silent : true,
316 silent : true,
319 store_history : false,
317 store_history : false,
320 user_variables : [],
318 user_variables : [],
321 user_expressions : {},
319 user_expressions : {},
322 allow_stdin : false
320 allow_stdin : false
323 };
321 };
324 callbacks = callbacks || {};
322 callbacks = callbacks || {};
325 if (callbacks.input_request !== undefined) {
323 if (callbacks.input_request !== undefined) {
326 content.allow_stdin = true;
324 content.allow_stdin = true;
327 }
325 }
328 $.extend(true, content, options)
326 $.extend(true, content, options)
329 $([IPython.events]).trigger('execution_request.Kernel', {kernel: this, content:content});
327 $([IPython.events]).trigger('execution_request.Kernel', {kernel: this, content:content});
330 var msg = this._get_msg("execute_request", content);
328 var msg = this._get_msg("execute_request", content);
331 this.shell_channel.send(JSON.stringify(msg));
329 this.shell_channel.send(JSON.stringify(msg));
332 this.set_callbacks_for_msg(msg.header.msg_id, callbacks);
330 this.set_callbacks_for_msg(msg.header.msg_id, callbacks);
333 return msg.header.msg_id;
331 return msg.header.msg_id;
334 };
332 };
335
333
336 /**
334 /**
337 * When calling this method pass a callbacks structure of the form:
335 * When calling this method pass a callbacks structure of the form:
338 *
336 *
339 * callbacks = {
337 * callbacks = {
340 * 'complete_reply': complete_reply_callback
338 * 'complete_reply': complete_reply_callback
341 * }
339 * }
342 *
340 *
343 * The `complete_reply_callback` will be passed the content object of the
341 * The `complete_reply_callback` will be passed the content object of the
344 * `complete_reply` message documented
342 * `complete_reply` message documented
345 * [here](http://ipython.org/ipython-doc/dev/development/messaging.html#complete)
343 * [here](http://ipython.org/ipython-doc/dev/development/messaging.html#complete)
346 *
344 *
347 * @method complete
345 * @method complete
348 * @param line {integer}
346 * @param line {integer}
349 * @param cursor_pos {integer}
347 * @param cursor_pos {integer}
350 * @param {dict} callbacks
348 * @param {dict} callbacks
351 * @param callbacks.complete_reply {function} `complete_reply_callback`
349 * @param callbacks.complete_reply {function} `complete_reply_callback`
352 *
350 *
353 */
351 */
354 Kernel.prototype.complete = function (line, cursor_pos, callbacks) {
352 Kernel.prototype.complete = function (line, cursor_pos, callbacks) {
355 callbacks = callbacks || {};
353 callbacks = callbacks || {};
356 var content = {
354 var content = {
357 text : '',
355 text : '',
358 line : line,
356 line : line,
359 block : null,
357 block : null,
360 cursor_pos : cursor_pos
358 cursor_pos : cursor_pos
361 };
359 };
362 var msg = this._get_msg("complete_request", content);
360 var msg = this._get_msg("complete_request", content);
363 this.shell_channel.send(JSON.stringify(msg));
361 this.shell_channel.send(JSON.stringify(msg));
364 this.set_callbacks_for_msg(msg.header.msg_id, callbacks);
362 this.set_callbacks_for_msg(msg.header.msg_id, callbacks);
365 return msg.header.msg_id;
363 return msg.header.msg_id;
366 };
364 };
367
365
368
366
369 Kernel.prototype.interrupt = function () {
367 Kernel.prototype.interrupt = function () {
370 if (this.running) {
368 if (this.running) {
371 $([IPython.events]).trigger('status_interrupting.Kernel', {kernel: this});
369 $([IPython.events]).trigger('status_interrupting.Kernel', {kernel: this});
372 $.post(this.kernel_url + "/interrupt");
370 $.post(this.kernel_url + "/interrupt");
373 };
371 };
374 };
372 };
375
373
376
374
377 Kernel.prototype.kill = function () {
375 Kernel.prototype.kill = function () {
378 if (this.running) {
376 if (this.running) {
379 this.running = false;
377 this.running = false;
380 var settings = {
378 var settings = {
381 cache : false,
379 cache : false,
382 type : "DELETE"
380 type : "DELETE"
383 };
381 };
384 $.ajax(this.kernel_url, settings);
382 $.ajax(this.kernel_url, settings);
385 };
383 };
386 };
384 };
387
385
388 Kernel.prototype.send_input_reply = function (input) {
386 Kernel.prototype.send_input_reply = function (input) {
389 var content = {
387 var content = {
390 value : input,
388 value : input,
391 };
389 };
392 $([IPython.events]).trigger('input_reply.Kernel', {kernel: this, content:content});
390 $([IPython.events]).trigger('input_reply.Kernel', {kernel: this, content:content});
393 var msg = this._get_msg("input_reply", content);
391 var msg = this._get_msg("input_reply", content);
394 this.stdin_channel.send(JSON.stringify(msg));
392 this.stdin_channel.send(JSON.stringify(msg));
395 return msg.header.msg_id;
393 return msg.header.msg_id;
396 };
394 };
397
395
398
396
399 // Reply handlers
397 // Reply handlers
400
398
401 Kernel.prototype.get_callbacks_for_msg = function (msg_id) {
399 Kernel.prototype.get_callbacks_for_msg = function (msg_id) {
402 var callbacks = this._msg_callbacks[msg_id];
400 var callbacks = this._msg_callbacks[msg_id];
403 return callbacks;
401 return callbacks;
404 };
402 };
405
403
406
404
407 Kernel.prototype.clear_callbacks_for_msg = function (msg_id) {
405 Kernel.prototype.clear_callbacks_for_msg = function (msg_id) {
408 if (this._msg_callbacks[msg_id] !== undefined ) {
406 if (this._msg_callbacks[msg_id] !== undefined ) {
409 delete this._msg_callbacks[msg_id];
407 delete this._msg_callbacks[msg_id];
410 }
408 }
411 };
409 };
412
410
413
411
414 Kernel.prototype.set_callbacks_for_msg = function (msg_id, callbacks) {
412 Kernel.prototype.set_callbacks_for_msg = function (msg_id, callbacks) {
415 this._msg_callbacks[msg_id] = callbacks || {};
413 this._msg_callbacks[msg_id] = callbacks || {};
416 };
414 };
417
415
418
416
419 Kernel.prototype._handle_shell_reply = function (e) {
417 Kernel.prototype._handle_shell_reply = function (e) {
420 var reply = $.parseJSON(e.data);
418 var reply = $.parseJSON(e.data);
421 $([IPython.events]).trigger('shell_reply.Kernel', {kernel: this, reply:reply});
419 $([IPython.events]).trigger('shell_reply.Kernel', {kernel: this, reply:reply});
422 var header = reply.header;
420 var header = reply.header;
423 var content = reply.content;
421 var content = reply.content;
424 var metadata = reply.metadata;
422 var metadata = reply.metadata;
425 var msg_type = header.msg_type;
423 var msg_type = header.msg_type;
426 var callbacks = this.get_callbacks_for_msg(reply.parent_header.msg_id);
424 var callbacks = this.get_callbacks_for_msg(reply.parent_header.msg_id);
427 if (callbacks !== undefined) {
425 if (callbacks !== undefined) {
428 var cb = callbacks[msg_type];
426 var cb = callbacks[msg_type];
429 if (cb !== undefined) {
427 if (cb !== undefined) {
430 cb(content, metadata);
428 cb(content, metadata);
431 }
429 }
432 };
430 };
433
431
434 if (content.payload !== undefined) {
432 if (content.payload !== undefined) {
435 var payload = content.payload || [];
433 var payload = content.payload || [];
436 this._handle_payload(callbacks, payload);
434 this._handle_payload(callbacks, payload);
437 }
435 }
438 };
436 };
439
437
440
438
441 Kernel.prototype._handle_payload = function (callbacks, payload) {
439 Kernel.prototype._handle_payload = function (callbacks, payload) {
442 var l = payload.length;
440 var l = payload.length;
443 // Payloads are handled by triggering events because we don't want the Kernel
441 // Payloads are handled by triggering events because we don't want the Kernel
444 // to depend on the Notebook or Pager classes.
442 // to depend on the Notebook or Pager classes.
445 for (var i=0; i<l; i++) {
443 for (var i=0; i<l; i++) {
446 if (payload[i].source === 'page') {
444 if (payload[i].source === 'page') {
447 var data = {'text':payload[i].text}
445 var data = {'text':payload[i].text}
448 $([IPython.events]).trigger('open_with_text.Pager', data);
446 $([IPython.events]).trigger('open_with_text.Pager', data);
449 } else if (payload[i].source === 'set_next_input') {
447 } else if (payload[i].source === 'set_next_input') {
450 if (callbacks.set_next_input !== undefined) {
448 if (callbacks.set_next_input !== undefined) {
451 callbacks.set_next_input(payload[i].text)
449 callbacks.set_next_input(payload[i].text)
452 }
450 }
453 }
451 }
454 };
452 };
455 };
453 };
456
454
457
455
458 Kernel.prototype._handle_iopub_reply = function (e) {
456 Kernel.prototype._handle_iopub_reply = function (e) {
459 var reply = $.parseJSON(e.data);
457 var reply = $.parseJSON(e.data);
460 var content = reply.content;
458 var content = reply.content;
461 var msg_type = reply.header.msg_type;
459 var msg_type = reply.header.msg_type;
462 var metadata = reply.metadata;
460 var metadata = reply.metadata;
463 var callbacks = this.get_callbacks_for_msg(reply.parent_header.msg_id);
461 var callbacks = this.get_callbacks_for_msg(reply.parent_header.msg_id);
464 if (msg_type !== 'status' && callbacks === undefined) {
462 if (msg_type !== 'status' && callbacks === undefined) {
465 // Message not from one of this notebook's cells and there are no
463 // Message not from one of this notebook's cells and there are no
466 // callbacks to handle it.
464 // callbacks to handle it.
467 return;
465 return;
468 }
466 }
469 var output_types = ['stream','display_data','pyout','pyerr'];
467 var output_types = ['stream','display_data','pyout','pyerr'];
470 if (output_types.indexOf(msg_type) >= 0) {
468 if (output_types.indexOf(msg_type) >= 0) {
471 var cb = callbacks['output'];
469 var cb = callbacks['output'];
472 if (cb !== undefined) {
470 if (cb !== undefined) {
473 cb(msg_type, content, metadata);
471 cb(msg_type, content, metadata);
474 }
472 }
475 } else if (msg_type === 'status') {
473 } else if (msg_type === 'status') {
476 if (content.execution_state === 'busy') {
474 if (content.execution_state === 'busy') {
477 $([IPython.events]).trigger('status_busy.Kernel', {kernel: this});
475 $([IPython.events]).trigger('status_busy.Kernel', {kernel: this});
478 } else if (content.execution_state === 'idle') {
476 } else if (content.execution_state === 'idle') {
479 $([IPython.events]).trigger('status_idle.Kernel', {kernel: this});
477 $([IPython.events]).trigger('status_idle.Kernel', {kernel: this});
480 } else if (content.execution_state === 'restarting') {
478 } else if (content.execution_state === 'restarting') {
481 // autorestarting is distinct from restarting,
479 // autorestarting is distinct from restarting,
482 // in that it means the kernel died and the server is restarting it.
480 // in that it means the kernel died and the server is restarting it.
483 // status_restarting sets the notification widget,
481 // status_restarting sets the notification widget,
484 // autorestart shows the more prominent dialog.
482 // autorestart shows the more prominent dialog.
485 $([IPython.events]).trigger('status_autorestarting.Kernel', {kernel: this});
483 $([IPython.events]).trigger('status_autorestarting.Kernel', {kernel: this});
486 $([IPython.events]).trigger('status_restarting.Kernel', {kernel: this});
484 $([IPython.events]).trigger('status_restarting.Kernel', {kernel: this});
487 } else if (content.execution_state === 'dead') {
485 } else if (content.execution_state === 'dead') {
488 this.stop_channels();
486 this.stop_channels();
489 $([IPython.events]).trigger('status_dead.Kernel', {kernel: this});
487 $([IPython.events]).trigger('status_dead.Kernel', {kernel: this});
490 };
488 };
491 } else if (msg_type === 'clear_output') {
489 } else if (msg_type === 'clear_output') {
492 var cb = callbacks['clear_output'];
490 var cb = callbacks['clear_output'];
493 if (cb !== undefined) {
491 if (cb !== undefined) {
494 cb(content, metadata);
492 cb(content, metadata);
495 }
493 }
496 };
494 };
497 };
495 };
498
496
499
497
500 Kernel.prototype._handle_input_request = function (e) {
498 Kernel.prototype._handle_input_request = function (e) {
501 var request = $.parseJSON(e.data);
499 var request = $.parseJSON(e.data);
502 var header = request.header;
500 var header = request.header;
503 var content = request.content;
501 var content = request.content;
504 var metadata = request.metadata;
502 var metadata = request.metadata;
505 var msg_type = header.msg_type;
503 var msg_type = header.msg_type;
506 if (msg_type !== 'input_request') {
504 if (msg_type !== 'input_request') {
507 console.log("Invalid input request!", request);
505 console.log("Invalid input request!", request);
508 return;
506 return;
509 }
507 }
510 var callbacks = this.get_callbacks_for_msg(request.parent_header.msg_id);
508 var callbacks = this.get_callbacks_for_msg(request.parent_header.msg_id);
511 if (callbacks !== undefined) {
509 if (callbacks !== undefined) {
512 var cb = callbacks[msg_type];
510 var cb = callbacks[msg_type];
513 if (cb !== undefined) {
511 if (cb !== undefined) {
514 cb(content, metadata);
512 cb(content, metadata);
515 }
513 }
516 };
514 };
517 };
515 };
518
516
519
517
520 IPython.Kernel = Kernel;
518 IPython.Kernel = Kernel;
521
519
522 return IPython;
520 return IPython;
523
521
524 }(IPython));
522 }(IPython));
525
523
@@ -1,101 +1,113 b''
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008-2011 The IPython Development Team
2 // Copyright (C) 2013 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 "use strict";
13
14
14 var Session = function(notebook_name, notebook_path, Notebook){
15 var utils = IPython.utils;
16
17 var Session = function(notebook_name, notebook_path, notebook){
15 this.kernel = null;
18 this.kernel = null;
16 this.id = null;
19 this.id = null;
17 this.name = notebook_name;
20 this.name = notebook_name;
18 this.path = notebook_path;
21 this.path = notebook_path;
19 this.notebook = Notebook;
22 this.notebook = notebook;
20 this._baseProjectUrl = Notebook.baseProjectUrl()
23 this._baseProjectUrl = notebook.baseProjectUrl();
21 };
24 };
22
25
23 Session.prototype.start = function() {
26 Session.prototype.start = function() {
24 var that = this
27 var that = this;
25 var notebook = {'notebook':{'name': this.name, 'path': this.path}}
28 var model = {
29 notebook : {
30 name : this.name,
31 path : this.path
32 }
33 };
26 var settings = {
34 var settings = {
27 processData : false,
35 processData : false,
28 cache : false,
36 cache : false,
29 type : "POST",
37 type : "POST",
30 data: JSON.stringify(notebook),
38 data: JSON.stringify(model),
31 dataType : "json",
39 dataType : "json",
32 success : $.proxy(this.start_kernel, that),
40 success : $.proxy(this.start_kernel, that),
33 };
41 };
34 var url = this._baseProjectUrl + 'api/sessions';
42 var url = utils.url_path_join(this._baseProjectUrl, 'api/sessions');
35 $.ajax(url, settings);
43 $.ajax(url, settings);
36 };
44 };
37
45
38 Session.prototype.notebook_rename = function (name, path) {
46 Session.prototype.notebook_rename = function (name, path) {
39 this.name = name;
47 this.name = name;
40 this.path = path;
48 this.path = path;
41 var notebook = {'notebook':{'name':name, 'path': path}};
49 var model = {
50 notebook : {
51 name : this.name,
52 path : this.path
53 }
54 };
42 var settings = {
55 var settings = {
43 processData : false,
56 processData : false,
44 cache : false,
57 cache : false,
45 type : "PATCH",
58 type : "PATCH",
46 data: JSON.stringify(notebook),
59 data: JSON.stringify(model),
47 dataType : "json",
60 dataType : "json",
48 };
61 };
49 var url = this._baseProjectUrl + 'api/sessions/' + this.session_id;
62 var url = utils.url_path_join(this._baseProjectUrl, 'api/sessions', this.session_id);
50 $.ajax(url, settings);
63 $.ajax(url, settings);
51 }
64 };
52
65
53 Session.prototype.delete_session = function() {
66 Session.prototype.delete_session = function() {
54 var settings = {
67 var settings = {
55 processData : false,
68 processData : false,
56 cache : false,
69 cache : false,
57 type : "DELETE",
70 type : "DELETE",
58 dataType : "json",
71 dataType : "json",
59 };
72 };
60 var url = this._baseProjectUrl + 'api/sessions/' + this.session_id;
73 var url = utils.url_path_join(this._baseProjectUrl, 'api/sessions', this.session_id);
61 $.ajax(url, settings);
74 $.ajax(url, settings);
62 };
75 };
63
76
64 // Kernel related things
77 // Kernel related things
65 /**
78 /**
66 * Start a new kernel and set it on each code cell.
79 * Start a new kernel and set it on each code cell.
67 *
80 *
68 * @method start_kernel
81 * @method start_kernel
69 */
82 */
70 Session.prototype.start_kernel = function (json) {
83 Session.prototype.start_kernel = function (json) {
71 this.id = json.id;
84 this.id = json.id;
72 this.kernel_content = json.kernel;
85 this.kernel_content = json.kernel;
73 var base_url = $('body').data('baseKernelUrl') + "api/kernels";
86 var base_url = utils.url_path_join($('body').data('baseKernelUrl'), "api/kernels");
74 this.kernel = new IPython.Kernel(base_url, this.session_id);
87 this.kernel = new IPython.Kernel(base_url, this.session_id);
75 this.kernel._kernel_started(this.kernel_content);
88 this.kernel._kernel_started(this.kernel_content);
76 };
89 };
77
90
78 /**
91 /**
79 * Prompt the user to restart the IPython kernel.
92 * Prompt the user to restart the IPython kernel.
80 *
93 *
81 * @method restart_kernel
94 * @method restart_kernel
82 */
95 */
83 Session.prototype.restart_kernel = function () {
96 Session.prototype.restart_kernel = function () {
84 this.kernel.restart();
97 this.kernel.restart();
85 };
98 };
86
99
87 Session.prototype.interrupt_kernel = function() {
100 Session.prototype.interrupt_kernel = function() {
88 this.kernel.interrupt();
101 this.kernel.interrupt();
89 };
102 };
90
103
91
104
92 Session.prototype.kill_kernel = function() {
105 Session.prototype.kill_kernel = function() {
93 this.kernel.kill();
106 this.kernel.kill();
94 };
107 };
95
108
96 IPython.Session = Session;
109 IPython.Session = Session;
97
110
98
99 return IPython;
111 return IPython;
100
112
101 }(IPython));
113 }(IPython));
General Comments 0
You need to be logged in to leave comments. Login now