aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files/js
diff options
context:
space:
mode:
Diffstat (limited to 'apps/files/js')
-rw-r--r--apps/files/js/app.js3
-rw-r--r--apps/files/js/file-upload.js7
-rw-r--r--apps/files/js/filelist.js153
-rw-r--r--apps/files/js/filemultiselectmenu.js1
-rw-r--r--apps/files/js/files.js4
-rw-r--r--apps/files/js/navigation.js90
-rw-r--r--apps/files/js/newfilemenu.js2
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` */