diff options
Diffstat (limited to 'apps/files/js')
-rw-r--r-- | apps/files/js/app.js | 3 | ||||
-rw-r--r-- | apps/files/js/file-upload.js | 7 | ||||
-rw-r--r-- | apps/files/js/filelist.js | 153 | ||||
-rw-r--r-- | apps/files/js/filemultiselectmenu.js | 1 | ||||
-rw-r--r-- | apps/files/js/files.js | 4 | ||||
-rw-r--r-- | apps/files/js/navigation.js | 90 | ||||
-rw-r--r-- | apps/files/js/newfilemenu.js | 2 |
7 files changed, 199 insertions, 61 deletions
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/file-upload.js b/apps/files/js/file-upload.js index bc1a4b36794..79d266a300b 100644 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -523,7 +523,9 @@ OC.Uploader.prototype = _.extend({ self.filesClient.createDirectory(fullPath).always(function(status) { // 405 is expected if the folder already exists if ((status >= 200 && status < 300) || status === 405) { - self.trigger('createdfolder', fullPath); + if (status !== 405) { + self.trigger('createdfolder', fullPath); + } deferred.resolve(); return; } @@ -845,7 +847,8 @@ OC.Uploader.prototype = _.extend({ type: 'PUT', dropZone: options.dropZone, // restrict dropZone to content div autoUpload: false, - sequentialUploads: true, + sequentialUploads: false, + limitConcurrentUploads: 10, //singleFileUploads is on by default, so the data.files array will always have length 1 /** * on first add of every selection diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 7ba650eb183..363f81a1a73 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); } @@ -354,15 +360,16 @@ this.$fileList.on('click','td.filename>a.name, td.filesize, td.date', _.bind(this._onClickFile, this)); - $.event.trigger({type: "droppedOnTrash"}); + this.$fileList.on("droppedOnFavorites", function (event, file) { + self.fileActions.triggerAction('Favorite', self.getModelForFile(file), self); + }); - var self=this; - this.$fileList.on("droppedOnTrash", function (event, filename, directory) { - //self.fileActions.triggerAction('Favorite', self.getModelForFile(file), self); - self.do_delete(filename, directory) + this.$fileList.on('droppedOnTrash', function (event, filename, directory) { + self.do_delete(filename, directory); }); 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')) { @@ -2524,7 +2600,7 @@ } try { - var newName = input.val(); + var newName = input.val().trim(); input.tooltip('hide'); form.remove(); @@ -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'); diff --git a/apps/files/js/files.js b/apps/files/js/files.js index 016aef05a96..a785a44ddd6 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -33,6 +33,9 @@ }, // update quota updateStorageQuotas: function() { + Files._updateStorageQuotasThrottled(); + }, + _updateStorageQuotas: function() { var state = Files.updateStorageQuotas; state.call = $.getJSON(OC.filePath('files','ajax','getstoragestats.php'),function(response) { Files.updateQuota(response); @@ -356,6 +359,7 @@ }; Files._updateStorageStatisticsDebounced = _.debounce(Files._updateStorageStatistics, 250); + Files._updateStorageQuotasThrottled = _.throttle(Files._updateStorageQuotas, 30000); OCA.Files.Files = Files; })(); diff --git a/apps/files/js/navigation.js b/apps/files/js/navigation.js index acfda3b6ce8..f8f15394ef0 100644 --- a/apps/files/js/navigation.js +++ b/apps/files/js/navigation.js @@ -62,40 +62,37 @@ * Setup UI events */ _setupEvents: function () { - this.$el.on('click', 'li a', _.bind(this._onClickItem, this)) + this.$el.on('click', 'li a', _.bind(this._onClickItem, this)); this.$el.on('click', 'li button', _.bind(this._onClickMenuButton, this)); - var trashElement=$(".nav-trashbin"); - - //this div is required to prefetch the icon, otherwise it takes a second to show up - trashElement.append("<div class='nav-icon-trashbin-starred'></div>") - trashElement.droppable({ - over: function( event, ui ) { - trashElement.addClass('dropzone-background') + var trashBinElement = $('.nav-trashbin'); + trashBinElement.droppable({ + over: function (event, ui) { + trashBinElement.addClass('dropzone-background'); }, - out: function( event, ui ) { - trashElement.removeClass('dropzone-background'); + out: function (event, ui) { + trashBinElement.removeClass('dropzone-background'); }, - activate: function( event, ui ) { - var elem=trashElement.find("a").first(); - elem.addClass('nav-icon-trashbin-starred').removeClass('nav-icon-trashbin'); + activate: function (event, ui) { + var element = trashBinElement.find('a').first(); + element.addClass('nav-icon-trashbin-starred').removeClass('nav-icon-trashbin'); }, - deactivate: function( event, ui ) { - var elem=trashElement.find("a").first(); - elem.addClass('nav-icon-trashbin').removeClass('nav-icon-trashbin-starred'); + deactivate: function (event, ui) { + var element = trashBinElement.find('a').first(); + element.addClass('nav-icon-trashbin').removeClass('nav-icon-trashbin-starred'); }, - drop: function( event, ui ) { + drop: function (event, ui) { + trashBinElement.removeClass('dropzone-background'); var $selectedFiles = $(ui.draggable); - if (ui.helper.find("tr").size()===1) { - var $tr = $selectedFiles.closest('tr'); - $selectedFiles.trigger("droppedOnTrash", $tr.attr("data-file"), $tr.attr('data-dir')); - }else{ - var item = ui.helper.find("tr"); - for(var i=0; i<item.length;i++){ - $selectedFiles.trigger("droppedOnTrash", item[i].getAttribute("data-file"), item[i].getAttribute("data-dir")); - } + // FIXME: when there are a lot of selected files the helper + // contains only a subset of them; the list of selected + // files should be gotten from the file list instead to + // ensure that all of them are removed. + var item = ui.helper.find('tr'); + for (var i = 0; i < item.length; i++) { + $selectedFiles.trigger('droppedOnTrash', item[i].getAttribute('data-file'), item[i].getAttribute('data-dir')); } } }); @@ -222,11 +219,52 @@ */ setInitialQuickaccessSettings: function () { var quickAccessKey = this.$quickAccessListKey; - var quickAccessMenu = document.getElementById(quickAccessKey) + var quickAccessMenu = document.getElementById(quickAccessKey); if (quickAccessMenu) { var list = quickAccessMenu.getElementsByTagName('li'); this.QuickSort(list, 0, list.length - 1); } + + var favoritesListElement = $(quickAccessMenu).parent(); + favoritesListElement.droppable({ + over: function (event, ui) { + favoritesListElement.addClass('dropzone-background'); + }, + out: function (event, ui) { + favoritesListElement.removeClass('dropzone-background'); + }, + activate: function (event, ui) { + var element = favoritesListElement.find('a').first(); + element.addClass('nav-icon-favorites-starred').removeClass('nav-icon-favorites'); + }, + deactivate: function (event, ui) { + var element = favoritesListElement.find('a').first(); + element.addClass('nav-icon-favorites').removeClass('nav-icon-favorites-starred'); + }, + drop: function (event, ui) { + favoritesListElement.removeClass('dropzone-background'); + + var $selectedFiles = $(ui.draggable); + + if (ui.helper.find('tr').size() === 1) { + var $tr = $selectedFiles.closest('tr'); + if ($tr.attr("data-favorite")) { + return; + } + $selectedFiles.trigger('droppedOnFavorites', $tr.attr('data-file')); + } else { + // FIXME: besides the issue described for dropping on + // the trash bin, for favoriting it is not possible to + // use the data from the helper; due to some bugs the + // tags are not always added to the selected files, and + // thus that data can not be accessed through the helper + // to prevent triggering the favorite action on an + // already favorited file (which would remove it from + // favorites). + OC.Notification.showTemporary(t('files', 'You can only favorite a single file or folder at a time')); + } + } + }); }, /** diff --git a/apps/files/js/newfilemenu.js b/apps/files/js/newfilemenu.js index 69450e97c2a..305af051271 100644 --- a/apps/files/js/newfilemenu.js +++ b/apps/files/js/newfilemenu.js @@ -167,7 +167,7 @@ event.preventDefault(); if (checkInput()) { - var newname = $input.val(); + var newname = $input.val().trim(); /* Find the right actionHandler that should be called. * Actions is retrieved by using `actionSpec.id` */ |