diff options
author | John Molakvoæ <skjnldsv@users.noreply.github.com> | 2019-01-30 10:21:23 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-30 10:21:23 +0100 |
commit | 53fd4997cc4abfbff35276e7b02be1eeca068a41 (patch) | |
tree | 0acb97cc0eac3e4a800b458c92ef80f235a8df8e /apps | |
parent | ecc8cccc4257580b0867000509bef0b22cec84f4 (diff) | |
parent | 907deab278d1c89784e26aa46fb0ff471ab04546 (diff) | |
download | nextcloud-server-53fd4997cc4abfbff35276e7b02be1eeca068a41.tar.gz nextcloud-server-53fd4997cc4abfbff35276e7b02be1eeca068a41.zip |
Merge pull request #12364 from tomasz-grobelny/file_range_select
Ability to select file ranges with mouse or touchscreen
Diffstat (limited to 'apps')
-rw-r--r-- | apps/files/css/files.scss | 5 | ||||
-rw-r--r-- | apps/files/js/app.js | 3 | ||||
-rw-r--r-- | apps/files/js/filelist.js | 141 | ||||
-rw-r--r-- | apps/files/js/filemultiselectmenu.js | 1 |
4 files changed, 124 insertions, 26 deletions
diff --git a/apps/files/css/files.scss b/apps/files/css/files.scss index 2c36ba8009a..502f8ea1f73 100644 --- a/apps/files/css/files.scss +++ b/apps/files/css/files.scss @@ -427,6 +427,11 @@ table td.selection { 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 */ #fileList tr td.selection>.selectCheckBox + label, .select-all + label { diff --git a/apps/files/js/app.js b/apps/files/js/app.js index c7393b871b8..4597dc9529a 100644 --- a/apps/files/js/app.js +++ b/apps/files/js/app.js @@ -100,11 +100,12 @@ displayName: t('files', 'Download'), iconClass: 'icon-download', }, + OCA.Files.FileList.MultiSelectMenuActions.ToggleSelectionModeAction, { name: 'delete', displayName: t('files', 'Delete'), iconClass: 'icon-delete', - } + }, ], sorting: { mode: $('#defaultFileSorting').val(), diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 7ba650eb183..a4402caa7cc 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -299,7 +299,13 @@ this.fileSummary = this._createSummary(); 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.$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('mouseover', 'td.selection', _.bind(this._onMouseOverCheckbox, this)); this.$el.on('show', _.bind(this._onShow, this)); this.$el.on('urlChanged', _.bind(this._onUrlChanged, this)); this.$el.find('.select-all').click(_.bind(this._onClickSelectAll, this)); @@ -418,7 +425,23 @@ $('#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) { + var actionFunction = _.find(this.multiSelectMenuItems, function (item) {return item.name === action;}).action; + if (actionFunction) { + actionFunction(ev); + return; + } switch (action) { case 'delete': this._onClickDeleteSelected(ev) @@ -685,7 +708,7 @@ * @param {Object} $tr single file row element * @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 oldData = !!this._selectedFiles[$tr.data('id')]; var data; @@ -711,6 +734,73 @@ 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 */ @@ -722,28 +812,11 @@ if (this._allowSelection && (event.ctrlKey || event.shiftKey)) { event.preventDefault(); if (event.shiftKey) { - 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 + 1; i < currentIndex; i++) { - this._selectFileEl($rows.eq(i), true); - } - } - else { - this._lastChecked = $tr; + this._selectRange($tr); + } else { + this._selectSingle($tr); } - var $checkbox = $tr.find('td.selection>.selectCheckBox'); - this._selectFileEl($tr, !$checkbox.prop('checked')); + this._lastChecked = $tr; this.updateSelectionSummary(); } else { // clicked directly on the name @@ -802,8 +875,11 @@ */ _onClickFileCheckbox: function(e) { var $tr = $(e.target).closest('tr'); - var state = !$tr.hasClass('selected'); - this._selectFileEl($tr, state); + if(this._getCurrentSelectionMode() === 'range') { + this._selectRange($tr); + } else { + this._selectSingle($tr); + } this._lastChecked = $tr; this.updateSelectionSummary(); if (this._detailsView && !this._detailsView.$el.hasClass('disappear')) { @@ -3540,6 +3616,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. * @namespace OCA.Files.FileList.Comparators diff --git a/apps/files/js/filemultiselectmenu.js b/apps/files/js/filemultiselectmenu.js index d50fe28eace..c0ee1d163c7 100644 --- a/apps/files/js/filemultiselectmenu.js +++ b/apps/files/js/filemultiselectmenu.js @@ -36,6 +36,7 @@ */ show: function(context) { this._context = context; + this.render(); this.$el.removeClass('hidden'); if (window.innerWidth < 480) { this.$el.removeClass('menu-center').addClass('menu-right'); |