Add more accessible method of selecting file ranges
Signed-off-by: Tomasz Grobelny <tomasz@grobelny.net>
This commit is contained in:
parent
54093e2bd6
commit
907deab278
|
@ -427,6 +427,11 @@ table td.selection {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Show checkbox with half opacity when selecting range */
|
||||||
|
#fileList tr.halfselected td.selection>.selectCheckBox + label:before {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
/* Use label to have bigger clickable size for checkbox */
|
/* Use label to have bigger clickable size for checkbox */
|
||||||
#fileList tr td.selection>.selectCheckBox + label,
|
#fileList tr td.selection>.selectCheckBox + label,
|
||||||
.select-all + label {
|
.select-all + label {
|
||||||
|
|
|
@ -100,11 +100,12 @@
|
||||||
displayName: t('files', 'Download'),
|
displayName: t('files', 'Download'),
|
||||||
iconClass: 'icon-download',
|
iconClass: 'icon-download',
|
||||||
},
|
},
|
||||||
|
OCA.Files.FileList.MultiSelectMenuActions.ToggleSelectionModeAction,
|
||||||
{
|
{
|
||||||
name: 'delete',
|
name: 'delete',
|
||||||
displayName: t('files', 'Delete'),
|
displayName: t('files', 'Delete'),
|
||||||
iconClass: 'icon-delete',
|
iconClass: 'icon-delete',
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
sorting: {
|
sorting: {
|
||||||
mode: $('#defaultFileSorting').val(),
|
mode: $('#defaultFileSorting').val(),
|
||||||
|
|
|
@ -299,7 +299,13 @@
|
||||||
this.fileSummary = this._createSummary();
|
this.fileSummary = this._createSummary();
|
||||||
|
|
||||||
if (options.multiSelectMenu) {
|
if (options.multiSelectMenu) {
|
||||||
this.fileMultiSelectMenu = new OCA.Files.FileMultiSelectMenu(options.multiSelectMenu);
|
this.multiSelectMenuItems = options.multiSelectMenu;
|
||||||
|
for (var i=0; i<this.multiSelectMenuItems.length; i++) {
|
||||||
|
if (_.isFunction(this.multiSelectMenuItems[i])) {
|
||||||
|
this.multiSelectMenuItems[i] = this.multiSelectMenuItems[i](this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.fileMultiSelectMenu = new OCA.Files.FileMultiSelectMenu(this.multiSelectMenuItems);
|
||||||
this.fileMultiSelectMenu.render();
|
this.fileMultiSelectMenu.render();
|
||||||
this.$el.find('.selectedActions').append(this.fileMultiSelectMenu.$el);
|
this.$el.find('.selectedActions').append(this.fileMultiSelectMenu.$el);
|
||||||
}
|
}
|
||||||
|
@ -363,6 +369,7 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$fileList.on('change', 'td.selection>.selectCheckBox', _.bind(this._onClickFileCheckbox, this));
|
this.$fileList.on('change', 'td.selection>.selectCheckBox', _.bind(this._onClickFileCheckbox, this));
|
||||||
|
this.$fileList.on('mouseover', 'td.selection', _.bind(this._onMouseOverCheckbox, this));
|
||||||
this.$el.on('show', _.bind(this._onShow, this));
|
this.$el.on('show', _.bind(this._onShow, this));
|
||||||
this.$el.on('urlChanged', _.bind(this._onUrlChanged, this));
|
this.$el.on('urlChanged', _.bind(this._onUrlChanged, this));
|
||||||
this.$el.find('.select-all').click(_.bind(this._onClickSelectAll, this));
|
this.$el.find('.select-all').click(_.bind(this._onClickSelectAll, this));
|
||||||
|
@ -418,7 +425,23 @@
|
||||||
$('#app-content').off('appresized', this._onResize);
|
$('#app-content').off('appresized', this._onResize);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_selectionMode: 'single',
|
||||||
|
_getCurrentSelectionMode: function () {
|
||||||
|
return this._selectionMode;
|
||||||
|
},
|
||||||
|
_onClickToggleSelectionMode: function () {
|
||||||
|
this._selectionMode = (this._selectionMode === 'range') ? 'single' : 'range';
|
||||||
|
if (this._selectionMode === 'single') {
|
||||||
|
this._removeHalfSelection();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
multiSelectMenuClick: function (ev, action) {
|
multiSelectMenuClick: function (ev, action) {
|
||||||
|
var actionFunction = _.find(this.multiSelectMenuItems, function (item) {return item.name === action;}).action;
|
||||||
|
if (actionFunction) {
|
||||||
|
actionFunction(ev);
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case 'delete':
|
case 'delete':
|
||||||
this._onClickDeleteSelected(ev)
|
this._onClickDeleteSelected(ev)
|
||||||
|
@ -685,7 +708,7 @@
|
||||||
* @param {Object} $tr single file row element
|
* @param {Object} $tr single file row element
|
||||||
* @param {bool} state true to select, false to deselect
|
* @param {bool} state true to select, false to deselect
|
||||||
*/
|
*/
|
||||||
_selectFileEl: function($tr, state, showDetailsView) {
|
_selectFileEl: function($tr, state) {
|
||||||
var $checkbox = $tr.find('td.selection>.selectCheckBox');
|
var $checkbox = $tr.find('td.selection>.selectCheckBox');
|
||||||
var oldData = !!this._selectedFiles[$tr.data('id')];
|
var oldData = !!this._selectedFiles[$tr.data('id')];
|
||||||
var data;
|
var data;
|
||||||
|
@ -711,6 +734,73 @@
|
||||||
this.$el.find('.select-all').prop('checked', this._selectionSummary.getTotal() === this.files.length);
|
this.$el.find('.select-all').prop('checked', this._selectionSummary.getTotal() === this.files.length);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_selectRange: function($tr) {
|
||||||
|
var checked = $tr.hasClass('selected');
|
||||||
|
var $lastTr = $(this._lastChecked);
|
||||||
|
var lastIndex = $lastTr.index();
|
||||||
|
var currentIndex = $tr.index();
|
||||||
|
var $rows = this.$fileList.children('tr');
|
||||||
|
|
||||||
|
// last clicked checkbox below current one ?
|
||||||
|
if (lastIndex > currentIndex) {
|
||||||
|
var aux = lastIndex;
|
||||||
|
lastIndex = currentIndex;
|
||||||
|
currentIndex = aux;
|
||||||
|
}
|
||||||
|
|
||||||
|
// auto-select everything in-between
|
||||||
|
for (var i = lastIndex; i <= currentIndex; i++) {
|
||||||
|
this._selectFileEl($rows.eq(i), !checked);
|
||||||
|
}
|
||||||
|
this._removeHalfSelection();
|
||||||
|
this._selectionMode = 'single';
|
||||||
|
},
|
||||||
|
|
||||||
|
_selectSingle: function($tr) {
|
||||||
|
var state = !$tr.hasClass('selected');
|
||||||
|
this._selectFileEl($tr, state);
|
||||||
|
},
|
||||||
|
|
||||||
|
_onMouseOverCheckbox: function(e) {
|
||||||
|
if (this._getCurrentSelectionMode() !== 'range') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var $currentTr = $(e.target).closest('tr');
|
||||||
|
|
||||||
|
var $lastTr = $(this._lastChecked);
|
||||||
|
var lastIndex = $lastTr.index();
|
||||||
|
var currentIndex = $currentTr.index();
|
||||||
|
var $rows = this.$fileList.children('tr');
|
||||||
|
|
||||||
|
// last clicked checkbox below current one ?
|
||||||
|
if (lastIndex > currentIndex) {
|
||||||
|
var aux = lastIndex;
|
||||||
|
lastIndex = currentIndex;
|
||||||
|
currentIndex = aux;
|
||||||
|
}
|
||||||
|
|
||||||
|
// auto-select everything in-between
|
||||||
|
this._removeHalfSelection();
|
||||||
|
for (var i = 0; i <= $rows.length; i++) {
|
||||||
|
var $tr = $rows.eq(i);
|
||||||
|
var $checkbox = $tr.find('td.selection>.selectCheckBox');
|
||||||
|
if(lastIndex <= i && i <= currentIndex) {
|
||||||
|
$tr.addClass('halfselected');
|
||||||
|
$checkbox.prop('checked', true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_removeHalfSelection: function() {
|
||||||
|
var $rows = this.$fileList.children('tr');
|
||||||
|
for (var i = 0; i <= $rows.length; i++) {
|
||||||
|
var $tr = $rows.eq(i);
|
||||||
|
$tr.removeClass('halfselected');
|
||||||
|
var $checkbox = $tr.find('td.selection>.selectCheckBox');
|
||||||
|
$checkbox.prop('checked', !!this._selectedFiles[$tr.data('id')]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event handler for when clicking on files to select them
|
* Event handler for when clicking on files to select them
|
||||||
*/
|
*/
|
||||||
|
@ -722,28 +812,11 @@
|
||||||
if (this._allowSelection && (event.ctrlKey || event.shiftKey)) {
|
if (this._allowSelection && (event.ctrlKey || event.shiftKey)) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (event.shiftKey) {
|
if (event.shiftKey) {
|
||||||
var $lastTr = $(this._lastChecked);
|
this._selectRange($tr);
|
||||||
var lastIndex = $lastTr.index();
|
} else {
|
||||||
var currentIndex = $tr.index();
|
this._selectSingle($tr);
|
||||||
var $rows = this.$fileList.children('tr');
|
|
||||||
|
|
||||||
// last clicked checkbox below current one ?
|
|
||||||
if (lastIndex > currentIndex) {
|
|
||||||
var aux = lastIndex;
|
|
||||||
lastIndex = currentIndex;
|
|
||||||
currentIndex = aux;
|
|
||||||
}
|
|
||||||
|
|
||||||
// auto-select everything in-between
|
|
||||||
for (var i = lastIndex + 1; i < currentIndex; i++) {
|
|
||||||
this._selectFileEl($rows.eq(i), true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
this._lastChecked = $tr;
|
||||||
this._lastChecked = $tr;
|
|
||||||
}
|
|
||||||
var $checkbox = $tr.find('td.selection>.selectCheckBox');
|
|
||||||
this._selectFileEl($tr, !$checkbox.prop('checked'));
|
|
||||||
this.updateSelectionSummary();
|
this.updateSelectionSummary();
|
||||||
} else {
|
} else {
|
||||||
// clicked directly on the name
|
// clicked directly on the name
|
||||||
|
@ -802,8 +875,11 @@
|
||||||
*/
|
*/
|
||||||
_onClickFileCheckbox: function(e) {
|
_onClickFileCheckbox: function(e) {
|
||||||
var $tr = $(e.target).closest('tr');
|
var $tr = $(e.target).closest('tr');
|
||||||
var state = !$tr.hasClass('selected');
|
if(this._getCurrentSelectionMode() === 'range') {
|
||||||
this._selectFileEl($tr, state);
|
this._selectRange($tr);
|
||||||
|
} else {
|
||||||
|
this._selectSingle($tr);
|
||||||
|
}
|
||||||
this._lastChecked = $tr;
|
this._lastChecked = $tr;
|
||||||
this.updateSelectionSummary();
|
this.updateSelectionSummary();
|
||||||
if (this._detailsView && !this._detailsView.$el.hasClass('disappear')) {
|
if (this._detailsView && !this._detailsView.$el.hasClass('disappear')) {
|
||||||
|
@ -3536,6 +3612,21 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FileList.MultiSelectMenuActions = {
|
||||||
|
ToggleSelectionModeAction: function(fileList) {
|
||||||
|
return {
|
||||||
|
name: 'toggleSelectionMode',
|
||||||
|
displayName: function(context) {
|
||||||
|
return t('files', 'Select file range');
|
||||||
|
},
|
||||||
|
iconClass: 'icon-fullscreen',
|
||||||
|
action: function() {
|
||||||
|
fileList._onClickToggleSelectionMode();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sort comparators.
|
* Sort comparators.
|
||||||
* @namespace OCA.Files.FileList.Comparators
|
* @namespace OCA.Files.FileList.Comparators
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
*/
|
*/
|
||||||
show: function(context) {
|
show: function(context) {
|
||||||
this._context = context;
|
this._context = context;
|
||||||
|
this.render();
|
||||||
this.$el.removeClass('hidden');
|
this.$el.removeClass('hidden');
|
||||||
if (window.innerWidth < 480) {
|
if (window.innerWidth < 480) {
|
||||||
this.$el.removeClass('menu-center').addClass('menu-right');
|
this.$el.removeClass('menu-center').addClass('menu-right');
|
||||||
|
|
Loading…
Reference in New Issue