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