Skip to content

Commit 1a24fa3

Browse files
committed
Added functionality for selecting multiple running items
1 parent 43df5af commit 1a24fa3

File tree

5 files changed

+260
-101
lines changed

5 files changed

+260
-101
lines changed

notebook/static/tree/js/kernellist.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ define([
2222
* notebook_path: string
2323
*/
2424
notebooklist.NotebookList.call(this, selector, $.extend({
25-
element_name: 'running'},
25+
element_name: 'running',
26+
element: '#running_list'},
2627
options));
2728
this.kernelspecs = this.sessions = null;
2829
this.events.on('kernelspecs_loaded.KernelSpec', $.proxy(this._kernelspecs_loaded, this));
@@ -45,10 +46,15 @@ define([
4546
};
4647

4748
KernelList.prototype.sessions_loaded = function (d) {
49+
var that = this;
4850
this.sessions = d;
4951
if (!this.kernelspecs) {
5052
return; // wait for kernelspecs before first load
5153
}
54+
55+
// Remember what was selected before the refresh.
56+
var selected_before = this.selected;
57+
5258
this.clear_list();
5359
var item, path, session, info;
5460
for (path in d) {
@@ -57,7 +63,7 @@ define([
5763
continue;
5864
}
5965
session = d[path];
60-
item = this.new_item(-1);
66+
item = this.new_item(-1, true);
6167
info = this.kernelspecs[session.kernel.name];
6268
this.add_link({
6369
name: path,
@@ -67,6 +73,20 @@ define([
6773
}, item);
6874
}
6975
$('#running_list_placeholder').toggle($.isEmptyObject(d));
76+
77+
// Reselect the items that were selected before. Notify listeners
78+
// that the selected items may have changed. O(n^2) operation.
79+
selected_before.forEach(function(item) {
80+
var list_items = that.element.children('.list_item');
81+
for (var i=0; i<list_items.length; i++) {
82+
var $list_item = $(list_items[i]);
83+
if ($list_item.data('path') === item.path) {
84+
$list_item.find('input[type=checkbox]').prop('checked', true);
85+
break;
86+
}
87+
}
88+
});
89+
this._selection_changed();
7090
};
7191

7292
KernelList.prototype.add_link = function (model, item) {

notebook/static/tree/js/main.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,13 @@ requirejs([
9797
contents: contents,
9898
session_list: session_list},
9999
common_options));
100-
var kernel_list = new kernellist.KernelList('#running_list', $.extend({
100+
var kernel_list = new kernellist.KernelList('#running_list_panel', $.extend({
101101
session_list: session_list},
102102
common_options));
103103

104104
var terminal_list;
105105
if (utils.get_body_data("terminalsAvailable") === "True") {
106-
terminal_list = new terminallist.TerminalList('#terminal_list', common_options);
106+
terminal_list = new terminallist.TerminalList('#terminal_list_panel', common_options);
107107
}
108108

109109
var login_widget = new loginwidget.LoginWidget('#login_widget', common_options);

notebook/static/tree/js/notebooklist.js

Lines changed: 71 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ define([
102102
* Dictionary of keyword arguments.
103103
* session_list: SessionList instance
104104
* element_name: string
105+
* element: string
105106
* base_url: string
106107
* notebook_path: string
107108
* contents: Contents instance
@@ -112,8 +113,11 @@ define([
112113
// allow code re-use by just changing element_name in kernellist.js
113114
this.element_name = options.element_name || 'notebook';
114115
this.selector = selector;
115-
if (this.selector !== undefined) {
116-
this.element = $(selector);
116+
if (this.selector !== undefined || options.element !== undefined) {
117+
if (options.element !== undefined)
118+
this.element = $(options.element);
119+
else
120+
this.element = $(selector);
117121
this.style();
118122
this.bind_events();
119123
}
@@ -162,6 +166,35 @@ define([
162166
return false;
163167
});
164168

169+
// Bind events for action buttons.
170+
$('#' + that.element_name + '_toolbar').find('.rename-button').click($.proxy(this.rename_selected, this));
171+
$('#' + that.element_name + '_toolbar').find('.move-button').click($.proxy(this.move_selected, this));
172+
$('#' + that.element_name + '_toolbar').find('.download-button').click($.proxy(this.download_selected, this));
173+
$('#' + that.element_name + '_toolbar').find('.shutdown-button').click($.proxy(this.shutdown_selected, this));
174+
$('#' + that.element_name + '_toolbar').find('.duplicate-button').click($.proxy(this.duplicate_selected, this));
175+
$('#' + that.element_name + '_toolbar').find('.view-button').click($.proxy(this.view_selected, this));
176+
$('#' + that.element_name + '_toolbar').find('.edit-button').click($.proxy(this.edit_selected, this));
177+
$('#' + that.element_name + '_toolbar').find('.delete-button').click($.proxy(this.delete_selected, this));
178+
179+
var select_all = $(that.selector).find('#select-all');
180+
select_all.change(function () {
181+
if (!select_all.prop('checked') || select_all.data('indeterminate')) {
182+
that.select('select-none');
183+
} else {
184+
that.select('select-all');
185+
}
186+
});
187+
$(that.selector).find('#button-select-all').click(function (e) {
188+
// toggle checkbox if the click doesn't come from the checkbox already
189+
if (!$(e.target).is('input[type=checkbox]')) {
190+
if (select_all.prop('checked') || select_all.data('indeterminate')) {
191+
that.select('select-none');
192+
} else {
193+
that.select('select-all');
194+
}
195+
}
196+
});
197+
165198
// Bind events for singleton controls.
166199
if (!NotebookList._bound_singletons) {
167200
NotebookList._bound_singletons = true;
@@ -212,39 +245,10 @@ define([
212245
e.preventDefault();
213246
});
214247

215-
// Bind events for action buttons.
216-
$('.rename-button').click($.proxy(this.rename_selected, this));
217-
$('.move-button').click($.proxy(this.move_selected, this));
218-
$('.download-button').click($.proxy(this.download_selected, this));
219-
$('.shutdown-button').click($.proxy(this.shutdown_selected, this));
220-
$('.duplicate-button').click($.proxy(this.duplicate_selected, this));
221-
$('.view-button').click($.proxy(this.view_selected, this));
222-
$('.edit-button').click($.proxy(this.edit_selected, this));
223-
$('.delete-button').click($.proxy(this.delete_selected, this));
224-
225248
// Bind events for selection menu buttons.
226249
$('#selector-menu').click(function (event) {
227250
that.select($(event.target).attr('id'));
228251
});
229-
var select_all = $('#select-all');
230-
select_all.change(function () {
231-
if (!select_all.prop('checked') || select_all.data('indeterminate')) {
232-
that.select('select-none');
233-
} else {
234-
that.select('select-all');
235-
}
236-
});
237-
238-
$('#button-select-all').click(function (e) {
239-
// toggle checkbox if the click doesn't come from the checkbox already
240-
if (!$(e.target).is('input[type=checkbox]')) {
241-
if (select_all.prop('checked') || select_all.data('indeterminate')) {
242-
that.select('select-none');
243-
} else {
244-
that.select('select-all');
245-
}
246-
}
247-
});
248252

249253
$('.sort-action').click(function(e) {
250254
var sort_on = e.target.id;
@@ -468,6 +472,7 @@ define([
468472
var type_order = {'directory':0,'notebook':1,'file':2};
469473

470474
NotebookList.prototype.draw_notebook_list = function (list, error_msg) {
475+
var that = this;
471476
// Remember what was selected before the refresh.
472477
var selected_before = this.selected;
473478

@@ -515,7 +520,7 @@ define([
515520
// Reselect the items that were selected before. Notify listeners
516521
// that the selected items may have changed. O(n^2) operation.
517522
selected_before.forEach(function(item) {
518-
var list_items = $('.list_item');
523+
var list_items = that.element.children('.list_item');
519524
for (var i=0; i<list_items.length; i++) {
520525
var $list_item = $(list_items[i]);
521526
if ($list_item.data('path') === item.path) {
@@ -592,8 +597,8 @@ define([
592597
} else if (selectable === true) {
593598
var that = this;
594599
row.click(function(e) {
595-
// toggle checkbox only if the click doesn't come from the checkbox or the link
596-
if (!$(e.target).is('span[class=item_name]') && !$(e.target).is('input[type=checkbox]')) {
600+
// toggle checkbox only if the click doesn't come from the checkbox or the link or any button
601+
if (!$(e.target).is('span[class=item_name]') && !$(e.target).is('input[type=checkbox]') && !$(e.target).is('button')) {
597602
checkbox.prop('checked', !checkbox.prop('checked'));
598603
}
599604
that._selection_changed();
@@ -634,7 +639,7 @@ define([
634639
*/
635640
NotebookList.prototype.select = function(selection_type) {
636641
var that = this;
637-
$('.list_item').each(function(index, item) {
642+
$(that.selector).find('.list_item').each(function(index, item) {
638643
var item_type = $(item).data('type');
639644
var state = false;
640645
state = state || (selection_type === "select-all");
@@ -689,8 +694,9 @@ define([
689694
var has_running_notebook = false;
690695
var has_directory = false;
691696
var has_file = false;
697+
var has_terminal = $('#terminal_list').find('.list_item :checked').length;
692698
var checked = 0;
693-
$('.list_item :checked').each(function(index, item) {
699+
$(that.selector).find('.list_item :checked').each(function(index, item) {
694700
var parent = $(item).parent().parent();
695701

696702
// If the item doesn't have an upload button, isn't the
@@ -716,48 +722,48 @@ define([
716722

717723
// Rename is only visible when one item is selected, and it is not a running notebook
718724
if (selected.length === 1 && !has_running_notebook) {
719-
$('.rename-button').css('display', 'inline-block');
725+
$('#' + that.element_name + '_toolbar').find('.rename-button').css('display', 'inline-block');
720726
} else {
721-
$('.rename-button').css('display', 'none');
727+
$('#' + that.element_name + '_toolbar').find('.rename-button').css('display', 'none');
722728
}
723729

724730
// Move is visible if at least one item is selected, and none of them
725731
// are a running notebook.
726732
if (selected.length > 0 && !has_running_notebook) {
727-
$('.move-button').css('display', 'inline-block');
733+
$('#' + that.element_name + '_toolbar').find('.move-button').css('display', 'inline-block');
728734
} else {
729-
$('.move-button').css('display', 'none');
735+
$('#' + that.element_name + '_toolbar').find('.move-button').css('display', 'none');
730736
}
731737

732738
// Download is only visible when one item is selected, and it is not a
733739
// running notebook or a directory
734740
// TODO(nhdaly): Add support for download multiple items at once.
735741
if (selected.length === 1 && !has_running_notebook && !has_directory) {
736-
$('.download-button').css('display', 'inline-block');
742+
$('#' + that.element_name + '_toolbar').find('.download-button').css('display', 'inline-block');
737743
} else {
738-
$('.download-button').css('display', 'none');
744+
$('#' + that.element_name + '_toolbar').find('.download-button').css('display', 'none');
739745
}
740746

741747
// Shutdown is only visible when one or more notebooks running notebooks
742748
// are selected and no non-notebook items are selected.
743-
if (has_running_notebook && !(has_file || has_directory)) {
744-
$('.shutdown-button').css('display', 'inline-block');
749+
if ((has_running_notebook || has_terminal) && !(has_file || has_directory)) {
750+
$('#' + that.element_name + '_toolbar').find('.shutdown-button').css('display', 'inline-block');
745751
} else {
746-
$('.shutdown-button').css('display', 'none');
752+
$('#' + that.element_name + '_toolbar').find('.shutdown-button').css('display', 'none');
747753
}
748754

749-
// Duplicate isn't visible when a directory is selected.
750-
if (selected.length > 0 && !has_directory) {
751-
$('.duplicate-button').css('display', 'inline-block');
755+
// Duplicate isn't visible when a directory or terminal is selected.
756+
if (selected.length > 0 && !has_directory && !has_terminal) {
757+
$('#' + that.element_name + '_toolbar').find('.duplicate-button').css('display', 'inline-block');
752758
} else {
753-
$('.duplicate-button').css('display', 'none');
759+
$('#' + that.element_name + '_toolbar').find('.duplicate-button').css('display', 'none');
754760
}
755761

756-
// Delete is visible if one or more items are selected.
757-
if (selected.length > 0) {
758-
$('.delete-button').css('display', 'inline-block');
762+
// Delete isn't visible when a terminal is selected.
763+
if (selected.length > 0 && !has_terminal) {
764+
$('#' + that.element_name + '_toolbar').find('.delete-button').css('display', 'inline-block');
759765
} else {
760-
$('.delete-button').css('display', 'none');
766+
$('#' + that.element_name + '_toolbar').find('.delete-button').css('display', 'none');
761767
}
762768

763769
// View is visible in the following case:
@@ -768,10 +774,10 @@ define([
768774
// If it's not editable or unknown, the default action should be view
769775
// already so no need to show the button.
770776
// That should include things like, html, py, txt, json....
771-
if (selected.length >= 1 && !has_directory) {
772-
$('.view-button').css('display', 'inline-block');
777+
if (selected.length >= 1 && !has_directory && !has_terminal) {
778+
$('#' + that.element_name + '_toolbar').find('.view-button').css('display', 'inline-block');
773779
} else {
774-
$('.view-button').css('display', 'none');
780+
$('#' + that.element_name + '_toolbar').find('.view-button').css('display', 'none');
775781
}
776782

777783
// Edit is visible when an item is unknown, that is to say:
@@ -781,19 +787,19 @@ define([
781787
// Indeed if it's editable the default action is already to edit.
782788
// And non editable files should not show edit button.
783789
// for unknown we'll assume users know what they are doing.
784-
if (selected.length >= 1 && !has_directory && selected.every(function(el) {
790+
if (selected.length >= 1 && !has_directory && !has_terminal && selected.every(function(el) {
785791
return that._is_editable(el);
786792
})) {
787-
$('.edit-button').css('display', 'inline-block');
793+
$('#' + that.element_name + '_toolbar').find('.edit-button').css('display', 'inline-block');
788794
} else {
789-
$('.edit-button').css('display', 'none');
795+
$('#' + that.element_name + '_toolbar').find('.edit-button').css('display', 'none');
790796
}
791797

792798
// If all of the items are selected, show the selector as checked. If
793799
// some of the items are selected, show it as checked. Otherwise,
794800
// uncheck it.
795801
var total = 0;
796-
$('.list_item input[type=checkbox]').each(function(index, item) {
802+
$(that.selector).find('.list_item input[type=checkbox]').each(function(index, item) {
797803
var parent = $(item).parent().parent();
798804
// If the item doesn't have an upload button and it's not the
799805
// breadcrumbs, it can be selected. Breadcrumbs path == ''.
@@ -802,7 +808,7 @@ define([
802808
}
803809
});
804810

805-
var select_all = $("#select-all");
811+
var select_all = $(that.selector).find("#select-all");
806812
if (checked === 0) {
807813
select_all.prop('checked', false);
808814
select_all.prop('indeterminate', false);
@@ -818,7 +824,7 @@ define([
818824
}
819825
// Update total counter
820826
checked = bidi.applyBidi(checked);
821-
$('#counter-select-all').html(checked===0 ? '&nbsp;' : checked);
827+
$(that.selector).find('#counter-select-all').html(checked===0 ? '&nbsp;' : checked);
822828

823829
//#issue 3961, update the checkbox aria-label when it changed
824830
if(selected.length>=1){
@@ -838,10 +844,10 @@ define([
838844
}
839845

840846
// If at aleast on item is selected, hide the selection instructions.
841-
if (checked > 0) {
842-
$('.dynamic-instructions').hide();
847+
if (checked > 0 || has_terminal) {
848+
$('#' + that.element_name + '_toolbar').find('.dynamic-instructions').hide();
843849
} else {
844-
$('.dynamic-instructions').show();
850+
$('#' + that.element_name + '_toolbar').find('.dynamic-instructions').show();
845851
}
846852
};
847853

0 commit comments

Comments
 (0)