##// END OF EJS Templates
fix new-notebook and change-kernel menus...
Min RK -
Show More
@@ -1,229 +1,233
1 1 // Copyright (c) IPython Development Team.
2 2 // Distributed under the terms of the Modified BSD License.
3 3
4 4 define([
5 'base/js/namespace',
6 5 'jquery',
6 'base/js/namespace',
7 'base/js/dialog',
7 8 'base/js/utils',
8 ], function(IPython, $, utils) {
9 ], function($, IPython, dialog, utils) {
9 10 "use strict";
10 11
11 12 var KernelSelector = function(selector, notebook) {
12 13 var that = this;
13 14 this.selector = selector;
14 15 this.notebook = notebook;
15 16 this.notebook.set_kernelselector(this);
16 17 this.events = notebook.events;
17 18 this.current_selection = null;
18 19 this.kernelspecs = {};
19 20 if (this.selector !== undefined) {
20 21 this.element = $(selector);
21 22 this.request_kernelspecs();
22 23 }
23 24 this.bind_events();
24 25 // Make the object globally available for user convenience & inspection
25 26 IPython.kernelselector = this;
26 27 this._finish_load = null;
27 28 this.loaded = new Promise(function(resolve, reject) {
28 29 that._finish_load = resolve;
29 30 });
30 31
31 32 Object.seal(this);
32 33 };
33 34
34 35 KernelSelector.prototype.request_kernelspecs = function() {
35 36 var url = utils.url_join_encode(this.notebook.base_url, 'api/kernelspecs');
36 37 utils.promising_ajax(url).then($.proxy(this._got_kernelspecs, this));
37 38 };
38 39
39 40 KernelSelector.prototype._got_kernelspecs = function(data) {
41 var that = this;
40 42 this.kernelspecs = data.kernelspecs;
41 43 var change_kernel_submenu = $("#menu-change-kernel-submenu");
42 44 var new_notebook_submenu = $("#menu-new-notebook-submenu");
43 45
44 46 var keys = Object.keys(data.kernelspecs).sort(function (a, b) {
45 47 // sort by display_name
46 48 var da = data.kernelspecs[a].spec.display_name;
47 49 var db = data.kernelspecs[b].spec.display_name;
48 50 if (da === db) {
49 51 return 0;
50 52 } else if (da > db) {
51 53 return 1;
52 54 } else {
53 55 return -1;
54 56 }
55 57 });
56 58
57 var i, ks, ks_submenu_entry;
59 keys.map(function (key) {
58 60 // Create the Kernel > Change kernel submenu
59 for (i = 0; i < keys.length; i++) {
60 ks = this.kernelspecs[keys[i]];
61 ks_submenu_entry = $("<li>").attr("id", "kernel-submenu-"+ks.name).append($('<a>')
61 var ks = data.kernelspecs[key];
62 change_kernel_submenu.append(
63 $("<li>").attr("id", "kernel-submenu-"+ks.name).append(
64 $('<a>')
62 65 .attr('href', '#')
63 66 .click(function(){
64 $.proxy(this.set_kernel, this, ks.name)
67 that.set_kernel(ks.name);
65 68 event.preventDefault();
66 69 })
67 .text(ks.spec.display_name));
68 change_kernel_submenu.append(ks_submenu_entry);
69 }
70
70 .text(ks.spec.display_name)
71 )
72 );
71 73 // Create the File > New Notebook submenu
72 for (i = 0; i < keys.length; i++) {
73 ks = this.kernelspecs[keys[i]];
74 ks_submenu_entry = $("<li>").attr("id", "new-notebook-submenu-"+ks.name).append($('<a>')
74 new_notebook_submenu.append(
75 $("<li>").attr("id", "new-notebook-submenu-"+ks.name).append(
76 $('<a>')
75 77 .attr('href', '#')
76 78 .click(function(){
77 $.proxy(this.new_notebook, this, ks.name)
79 that.new_notebook(ks.name);
78 80 event.preventDefault();
79 81 })
80 .text(ks.spec.display_name));
81 new_notebook_submenu.append(ks_submenu_entry);
82 }
82 .text(ks.spec.display_name)
83 )
84 );
85
86 });
83 87 // trigger loaded promise
84 88 this._finish_load();
85 89 };
86 90
87 91 KernelSelector.prototype._spec_changed = function (event, ks) {
88 92 /** event handler for spec_changed */
89 93
90 94 // update selection
91 95 this.current_selection = ks.name;
92 96
93 97 // put the current kernel at the top of File > New Notebook
94 98 var cur_kernel_entry = $("#new-notebook-submenu-" + ks.name);
95 99 var parent = cur_kernel_entry.parent();
96 100 // do something only if there is more than one kernel
97 101 if (parent.children().length > 1) {
98 102 // first, sort back the submenu
99 103 parent.append(
100 104 parent.children("li[class!='divider']").sort(
101 105 function (a,b) {
102 106 var da = $("a",a).text();
103 107 var db = $("a",b).text();
104 108 if (da === db) {
105 109 return 0;
106 110 } else if (da > db) {
107 111 return 1;
108 112 } else {
109 113 return -1;
110 114 }}));
111 115 // then, if there is no divider yet, add one
112 116 if (!parent.children("li[class='divider']").length) {
113 117 parent.prepend($("<li>").attr("class","divider"));
114 118 }
115 119 // finally, put the current kernel at the top
116 120 parent.prepend(cur_kernel_entry);
117 121 }
118 122
119 123 // load logo
120 124 var logo_img = this.element.find("img.current_kernel_logo");
121 125 $("#kernel_indicator").find('.kernel_indicator_name').text(ks.spec.display_name);
122 126 if (ks.resources['logo-64x64']) {
123 127 logo_img.attr("src", ks.resources['logo-64x64']);
124 128 logo_img.show();
125 129 } else {
126 130 logo_img.hide();
127 131 }
128 132
129 133 // load kernel css
130 134 var css_url = ks.resources['kernel.css'];
131 135 if (css_url) {
132 136 $('#kernel-css').attr('href', css_url);
133 137 } else {
134 138 $('#kernel-css').attr('href', '');
135 139 }
136 140
137 141 // load kernel js
138 142 if (ks.resources['kernel.js']) {
139 143 require([ks.resources['kernel.js']],
140 144 function (kernel_mod) {
141 145 if (kernel_mod && kernel_mod.onload) {
142 146 kernel_mod.onload();
143 147 } else {
144 148 console.warn("Kernel " + ks.name + " has a kernel.js file that does not contain "+
145 149 "any asynchronous module definition. This is undefined behavior "+
146 150 "and not recommended.");
147 151 }
148 152 }, function (err) {
149 153 console.warn("Failed to load kernel.js from ", ks.resources['kernel.js'], err);
150 154 }
151 155 );
152 156 }
153 157 };
154 158
155 159 KernelSelector.prototype.set_kernel = function (kernel_name) {
156 160 /** set the kernel by name, ensuring kernelspecs have been loaded, first */
157 161 var that = this;
158 162 return this.loaded.then(function () {
159 163 that._set_kernel(kernel_name);
160 164 });
161 165 };
162 166
163 167 KernelSelector.prototype._set_kernel = function (kernel_name) {
164 168 /** Actually set the kernel (kernelspecs have been loaded) */
165 169 if (kernel_name === this.current_selection) {
166 170 // only trigger event if value changed
167 171 return;
168 172 }
169 173 var ks = this.kernelspecs[kernel_name];
170 174 if (this.notebook._session_starting) {
171 175 console.error("Cannot change kernel while waiting for pending session start.");
172 176 return;
173 177 }
174 178 this.current_selection = kernel_name;
175 179 this.events.trigger('spec_changed.Kernel', ks);
176 180 };
177 181
178 182 KernelSelector.prototype.new_notebook = function (kernel_name) {
179 183
180 184 var w = window.open();
181 185 // Create a new notebook in the same path as the current
182 186 // notebook's path.
183 187 var that = this;
184 188 var parent = utils.url_path_split(that.notebook.notebook_path)[0];
185 189 that.notebook.contents.new_untitled(parent, {type: "notebook"}).then(
186 190 function (data) {
187 191 var url = utils.url_join_encode(
188 192 that.notebook.base_url, 'notebooks', data.path
189 193 );
190 194 url += "?kernel_name=" + kernel_name;
191 195 w.location = url;
192 196 },
193 197 function(error) {
194 198 w.close();
195 199 dialog.modal({
196 200 title : 'Creating Notebook Failed',
197 201 body : "The error was: " + error.message,
198 202 buttons : {'OK' : {'class' : 'btn-primary'}}
199 203 });
200 204 }
201 205 );
202 206 };
203 207
204 208 KernelSelector.prototype.lock_switch = function() {
205 209 // should set a flag and display warning+reload if user want to
206 210 // re-change kernel. As UI discussion never finish
207 211 // making that a separate PR.
208 212 console.warn('switching kernel is not guaranteed to work !');
209 213 };
210 214
211 215 KernelSelector.prototype.bind_events = function() {
212 216 var that = this;
213 217 this.events.on('spec_changed.Kernel', $.proxy(this._spec_changed, this));
214 218
215 219 this.events.on('kernel_created.Session', function (event, data) {
216 220 that.set_kernel(data.kernel.name);
217 221 });
218 222
219 223 var logo_img = this.element.find("img.current_kernel_logo");
220 224 logo_img.on("load", function() {
221 225 logo_img.show();
222 226 });
223 227 logo_img.on("error", function() {
224 228 logo_img.hide();
225 229 });
226 230 };
227 231
228 232 return {'KernelSelector': KernelSelector};
229 233 });
General Comments 0
You need to be logged in to leave comments. Login now