Fix file selection for infinite scrolling
- moved file selection code to FileList - fix selection summary when all files are selected - nextPage now auto-selects files if "select all" checkbox is checked - fixed trashbin to use the same selection logic as FileList
This commit is contained in:
parent
9f62059efa
commit
9c2fbea6a4
|
@ -310,7 +310,6 @@ a.action>img { max-height:16px; max-width:16px; vertical-align:text-bottom; }
|
||||||
|
|
||||||
/* Actions for selected files */
|
/* Actions for selected files */
|
||||||
.selectedActions {
|
.selectedActions {
|
||||||
display: none;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -1px;
|
top: -1px;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global OC, t, n, FileList, FileActions, Files, FileSummary, BreadCrumb */
|
/* global OC, t, n, FileList, FileActions, Files, FileSummary, BreadCrumb */
|
||||||
/* global procesSelection, dragOptions, folderDropOptions */
|
/* global dragOptions, folderDropOptions */
|
||||||
window.FileList = {
|
window.FileList = {
|
||||||
appName: t('files', 'Files'),
|
appName: t('files', 'Files'),
|
||||||
isEmpty: true,
|
isEmpty: true,
|
||||||
|
@ -60,6 +60,142 @@ window.FileList = {
|
||||||
var width = $(this).width();
|
var width = $(this).width();
|
||||||
FileList.breadcrumb.resize(width, false);
|
FileList.breadcrumb.resize(width, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.$fileList.on('click','td.filename a', this._onClickFile);
|
||||||
|
this.$fileList.on('change', 'td.filename input:checkbox', this._onClickFileCheckbox);
|
||||||
|
this.$el.find('#select_all').click(this._onClickSelectAll);
|
||||||
|
this.$el.find('.download').click(this._onClickDownloadSelected);
|
||||||
|
this.$el.find('.delete-selected').click(this._onClickDeleteSelected);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler for when clicking on files to select them
|
||||||
|
*/
|
||||||
|
_onClickFile: function(event) {
|
||||||
|
if (event.ctrlKey || event.shiftKey) {
|
||||||
|
event.preventDefault();
|
||||||
|
if (event.shiftKey) {
|
||||||
|
var last = $(FileList._lastChecked).parent().parent().prevAll().length;
|
||||||
|
var first = $(this).parent().parent().prevAll().length;
|
||||||
|
var start = Math.min(first, last);
|
||||||
|
var end = Math.max(first, last);
|
||||||
|
var rows = $(this).parent().parent().parent().children('tr');
|
||||||
|
for (var i = start; i < end; i++) {
|
||||||
|
$(rows).each(function(index) {
|
||||||
|
if (index === i) {
|
||||||
|
var checkbox = $(this).children().children('input:checkbox');
|
||||||
|
$(checkbox).attr('checked', 'checked');
|
||||||
|
$(checkbox).parent().parent().addClass('selected');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var checkbox = $(this).parent().children('input:checkbox');
|
||||||
|
FileList._lastChecked = checkbox;
|
||||||
|
if ($(checkbox).attr('checked')) {
|
||||||
|
$(checkbox).removeAttr('checked');
|
||||||
|
$(checkbox).parent().parent().removeClass('selected');
|
||||||
|
$('#select_all').removeAttr('checked');
|
||||||
|
} else {
|
||||||
|
$(checkbox).attr('checked', 'checked');
|
||||||
|
$(checkbox).parent().parent().toggleClass('selected');
|
||||||
|
var selectedCount = $('td.filename input:checkbox:checked').length;
|
||||||
|
if (selectedCount === $('td.filename input:checkbox').length) {
|
||||||
|
$('#select_all').attr('checked', 'checked');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FileList.updateSelectionSummary();
|
||||||
|
} else {
|
||||||
|
var filename=$(this).parent().parent().attr('data-file');
|
||||||
|
var tr = FileList.findFileEl(filename);
|
||||||
|
var renaming=tr.data('renaming');
|
||||||
|
if (!renaming) {
|
||||||
|
FileActions.currentFile = $(this).parent();
|
||||||
|
var mime=FileActions.getCurrentMimeType();
|
||||||
|
var type=FileActions.getCurrentType();
|
||||||
|
var permissions = FileActions.getCurrentPermissions();
|
||||||
|
var action=FileActions.getDefault(mime,type, permissions);
|
||||||
|
if (action) {
|
||||||
|
event.preventDefault();
|
||||||
|
action(filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler for when clicking on a file's checkbox
|
||||||
|
*/
|
||||||
|
_onClickFileCheckbox: function(event) {
|
||||||
|
// FIXME: not sure what the difference is supposed to be with FileList._onClickFile
|
||||||
|
if (event.shiftKey) {
|
||||||
|
var last = $(FileList._lastChecked).parent().parent().prevAll().length;
|
||||||
|
var first = $(this).parent().parent().prevAll().length;
|
||||||
|
var start = Math.min(first, last);
|
||||||
|
var end = Math.max(first, last);
|
||||||
|
var rows = $(this).parent().parent().parent().children('tr');
|
||||||
|
for (var i = start; i < end; i++) {
|
||||||
|
$(rows).each(function(index) {
|
||||||
|
if (index === i) {
|
||||||
|
var checkbox = $(this).children().children('input:checkbox');
|
||||||
|
$(checkbox).attr('checked', 'checked');
|
||||||
|
$(checkbox).parent().parent().addClass('selected');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var selectedCount=$('td.filename input:checkbox:checked').length;
|
||||||
|
$(this).parent().parent().toggleClass('selected');
|
||||||
|
if (!$(this).attr('checked')) {
|
||||||
|
$('#select_all').attr('checked',false);
|
||||||
|
} else {
|
||||||
|
if (selectedCount===$('td.filename input:checkbox').length) {
|
||||||
|
$('#select_all').attr('checked',true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FileList.updateSelectionSummary();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler for when selecting/deselecting all files
|
||||||
|
*/
|
||||||
|
_onClickSelectAll: function(e) {
|
||||||
|
var checked = $(this).prop('checked');
|
||||||
|
FileList.$fileList.find('td.filename input:checkbox').prop('checked', checked)
|
||||||
|
.parent().parent().toggleClass('selected', checked);
|
||||||
|
FileList.updateSelectionSummary();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler for when clicking on "Download" for the selected files
|
||||||
|
*/
|
||||||
|
_onClickDownloadSelected: function(event) {
|
||||||
|
var files;
|
||||||
|
var dir = FileList.getCurrentDirectory();
|
||||||
|
if (FileList.isAllSelected()) {
|
||||||
|
files = OC.basename(dir);
|
||||||
|
dir = OC.dirname(dir) || '/';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
files = FileList.getSelectedFiles('name');
|
||||||
|
}
|
||||||
|
OC.Notification.show(t('files','Your download is being prepared. This might take some time if the files are big.'));
|
||||||
|
OC.redirect(Files.getDownloadUrl(files, dir));
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler for when clicking on "Delete" for the selected files
|
||||||
|
*/
|
||||||
|
_onClickDeleteSelected: function(event) {
|
||||||
|
var files = null;
|
||||||
|
if (!FileList.isAllSelected()) {
|
||||||
|
files = FileList.getSelectedFiles('name');
|
||||||
|
}
|
||||||
|
FileList.do_delete(files);
|
||||||
|
event.preventDefault();
|
||||||
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,7 +215,7 @@ window.FileList = {
|
||||||
if (this.pageNumber + 1 >= this.totalPages) {
|
if (this.pageNumber + 1 >= this.totalPages) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ($(window).scrollTop() + $(window).height() > $(document).height() - 20) {
|
if ($(window).scrollTop() + $(window).height() > $(document).height() - 500) {
|
||||||
this._nextPage(true);
|
this._nextPage(true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -113,7 +249,7 @@ window.FileList = {
|
||||||
if (result) {
|
if (result) {
|
||||||
if (result.status === 'success') {
|
if (result.status === 'success') {
|
||||||
FileList.remove(file);
|
FileList.remove(file);
|
||||||
procesSelection();
|
FileList.updateSelectionSummary();
|
||||||
$('#notification').hide();
|
$('#notification').hide();
|
||||||
} else {
|
} else {
|
||||||
$('#notification').hide();
|
$('#notification').hide();
|
||||||
|
@ -152,13 +288,30 @@ window.FileList = {
|
||||||
return this.$fileList.find('tr').filterAttr('data-file', fileName);
|
return this.$fileList.find('tr').filterAttr('data-file', fileName);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the file data from a given file element.
|
||||||
|
* @param $el file tr element
|
||||||
|
* @return file data
|
||||||
|
*/
|
||||||
|
elementToFile: function($el){
|
||||||
|
return {
|
||||||
|
id: parseInt($el.attr('data-id'), 10),
|
||||||
|
name: $el.attr('data-file'),
|
||||||
|
mimetype: $el.attr('data-mime'),
|
||||||
|
type: $el.attr('data-type'),
|
||||||
|
size: parseInt($el.attr('data-size'), 10),
|
||||||
|
etag: $el.attr('data-etag'),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appends the next page of files into the table
|
* Appends the next page of files into the table
|
||||||
* @param animate true to animate the new elements
|
* @param animate true to animate the new elements
|
||||||
*/
|
*/
|
||||||
_nextPage: function(animate) {
|
_nextPage: function(animate) {
|
||||||
var tr, index, count = this.pageSize,
|
var tr, index, count = this.pageSize,
|
||||||
newTrs = [];
|
newTrs = [],
|
||||||
|
selected = this.isAllSelected();
|
||||||
|
|
||||||
if (this.pageNumber + 1 >= this.totalPages) {
|
if (this.pageNumber + 1 >= this.totalPages) {
|
||||||
return;
|
return;
|
||||||
|
@ -169,6 +322,10 @@ window.FileList = {
|
||||||
|
|
||||||
while (count > 0 && index < this.files.length) {
|
while (count > 0 && index < this.files.length) {
|
||||||
tr = this.add(this.files[index], {updateSummary: false});
|
tr = this.add(this.files[index], {updateSummary: false});
|
||||||
|
if (selected) {
|
||||||
|
tr.addClass('selected');
|
||||||
|
tr.find('input:checkbox').prop('checked', true);
|
||||||
|
}
|
||||||
if (animate) {
|
if (animate) {
|
||||||
tr.addClass('appear transparent'); // TODO
|
tr.addClass('appear transparent'); // TODO
|
||||||
newTrs.push(tr);
|
newTrs.push(tr);
|
||||||
|
@ -201,6 +358,9 @@ window.FileList = {
|
||||||
this.$fileList.detach();
|
this.$fileList.detach();
|
||||||
this.$fileList.empty();
|
this.$fileList.empty();
|
||||||
|
|
||||||
|
// clear "Select all" checkbox
|
||||||
|
$('#select_all').prop('checked', false);
|
||||||
|
|
||||||
this.isEmpty = this.files.length === 0;
|
this.isEmpty = this.files.length === 0;
|
||||||
this._nextPage();
|
this._nextPage();
|
||||||
|
|
||||||
|
@ -215,7 +375,7 @@ window.FileList = {
|
||||||
|
|
||||||
this.fileSummary.calculate(filesArray);
|
this.fileSummary.calculate(filesArray);
|
||||||
|
|
||||||
procesSelection();
|
FileList.updateSelectionSummary();
|
||||||
$(window).scrollTop(0);
|
$(window).scrollTop(0);
|
||||||
|
|
||||||
this.$fileList.trigger(jQuery.Event("updated"));
|
this.$fileList.trigger(jQuery.Event("updated"));
|
||||||
|
@ -580,10 +740,14 @@ window.FileList = {
|
||||||
* @param name name of the file to remove
|
* @param name name of the file to remove
|
||||||
* @param options optional options as map:
|
* @param options optional options as map:
|
||||||
* "updateSummary": true to update the summary (default), false otherwise
|
* "updateSummary": true to update the summary (default), false otherwise
|
||||||
|
* @return deleted element
|
||||||
*/
|
*/
|
||||||
remove:function(name, options){
|
remove:function(name, options){
|
||||||
options = options || {};
|
options = options || {};
|
||||||
var fileEl = FileList.findFileEl(name);
|
var fileEl = FileList.findFileEl(name);
|
||||||
|
if (!fileEl.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (fileEl.data('permissions') & OC.PERMISSION_DELETE) {
|
if (fileEl.data('permissions') & OC.PERMISSION_DELETE) {
|
||||||
// file is only draggable when delete permissions are set
|
// file is only draggable when delete permissions are set
|
||||||
fileEl.find('td.filename').draggable('destroy');
|
fileEl.find('td.filename').draggable('destroy');
|
||||||
|
@ -824,21 +988,22 @@ window.FileList = {
|
||||||
function(result) {
|
function(result) {
|
||||||
if (result.status === 'success') {
|
if (result.status === 'success') {
|
||||||
if (params.allfiles) {
|
if (params.allfiles) {
|
||||||
// clear whole list
|
FileList.setFiles([]);
|
||||||
$('#fileList tr').remove();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$.each(files,function(index,file) {
|
$.each(files,function(index,file) {
|
||||||
var fileEl = FileList.remove(file, {updateSummary: false});
|
var fileEl = FileList.remove(file, {updateSummary: false});
|
||||||
|
// FIXME: not sure why we need this after the
|
||||||
|
// element isn't even in the DOM any more
|
||||||
fileEl.find('input[type="checkbox"]').prop('checked', false);
|
fileEl.find('input[type="checkbox"]').prop('checked', false);
|
||||||
fileEl.removeClass('selected');
|
fileEl.removeClass('selected');
|
||||||
FileList.fileSummary.remove({type: fileEl.attr('data-type'), size: fileEl.attr('data-size')});
|
FileList.fileSummary.remove({type: fileEl.attr('data-type'), size: fileEl.attr('data-size')});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
procesSelection();
|
|
||||||
checkTrashStatus();
|
checkTrashStatus();
|
||||||
FileList.updateEmptyContent();
|
FileList.updateEmptyContent();
|
||||||
FileList.fileSummary.update();
|
FileList.fileSummary.update();
|
||||||
|
FileList.updateSelectionSummary();
|
||||||
Files.updateStorageStatistics();
|
Files.updateStorageStatistics();
|
||||||
} else {
|
} else {
|
||||||
if (result.status === 'error' && result.data.message) {
|
if (result.status === 'error' && result.data.message) {
|
||||||
|
@ -941,14 +1106,95 @@ window.FileList = {
|
||||||
$(e).removeClass("searchresult");
|
$(e).removeClass("searchresult");
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Update UI based on the current selection
|
||||||
|
*/
|
||||||
|
updateSelectionSummary: function() {
|
||||||
|
var allSelected = this.isAllSelected();
|
||||||
|
var selected;
|
||||||
|
var summary = {
|
||||||
|
totalFiles: 0,
|
||||||
|
totalDirs: 0,
|
||||||
|
totalSize: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
if (allSelected) {
|
||||||
|
summary = this.fileSummary.summary;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
selected = this.getSelectedFiles();
|
||||||
|
for (var i = 0; i < selected.length; i++ ){
|
||||||
|
if (selected[i].type === 'dir') {
|
||||||
|
summary.totalDirs++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
summary.totalFiles++;
|
||||||
|
}
|
||||||
|
summary.totalSize += parseInt(selected[i].size, 10) || 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (summary.totalFiles === 0 && summary.totalDirs === 0) {
|
||||||
|
$('#headerName span.name').text(t('files','Name'));
|
||||||
|
$('#headerSize').text(t('files','Size'));
|
||||||
|
$('#modified').text(t('files','Modified'));
|
||||||
|
$('table').removeClass('multiselect');
|
||||||
|
$('.selectedActions').addClass('hidden');
|
||||||
|
$('#select_all').removeAttr('checked');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('.selectedActions').removeClass('hidden');
|
||||||
|
$('#headerSize').text(humanFileSize(summary.totalSize));
|
||||||
|
var selection = '';
|
||||||
|
if (summary.totalDirs > 0) {
|
||||||
|
selection += n('files', '%n folder', '%n folders', summary.totalDirs);
|
||||||
|
if (summary.totalFiles > 0) {
|
||||||
|
selection += ' & ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (summary.totalFiles > 0) {
|
||||||
|
selection += n('files', '%n file', '%n files', summary.totalFiles);
|
||||||
|
}
|
||||||
|
$('#headerName span.name').text(selection);
|
||||||
|
$('#modified').text('');
|
||||||
|
$('table').addClass('multiselect');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether all files are selected
|
* Returns whether all files are selected
|
||||||
* @return true if all files are selected, false otherwise
|
* @return true if all files are selected, false otherwise
|
||||||
*/
|
*/
|
||||||
isAllSelected: function() {
|
isAllSelected: function() {
|
||||||
return $('#select_all').prop('checked');
|
return this.$el.find('#select_all').prop('checked');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief get a list of selected files
|
||||||
|
* @param {string} property (option) the property of the file requested
|
||||||
|
* @return {array}
|
||||||
|
*
|
||||||
|
* possible values for property: name, mime, size and type
|
||||||
|
* if property is set, an array with that property for each file is returnd
|
||||||
|
* if it's ommited an array of objects with all properties is returned
|
||||||
|
*/
|
||||||
|
getSelectedFiles: function(property) {
|
||||||
|
var elements=$('td.filename input:checkbox:checked').parent().parent();
|
||||||
|
var files=[];
|
||||||
|
elements.each(function(i,element) {
|
||||||
|
// TODO: make the json format the same as in FileList.add()
|
||||||
|
var file = FileList.elementToFile($(element));
|
||||||
|
// FIXME: legacy attributes
|
||||||
|
file.origin = file.id;
|
||||||
|
file.mime = file.mimetype;
|
||||||
|
if (property) {
|
||||||
|
files.push(file[property]);
|
||||||
|
} else {
|
||||||
|
files.push(file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return files;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
FileList.initialize();
|
FileList.initialize();
|
||||||
|
|
|
@ -209,7 +209,7 @@ $(document).ready(function() {
|
||||||
// Trigger cancelling of file upload
|
// Trigger cancelling of file upload
|
||||||
$('#uploadprogresswrapper .stop').on('click', function() {
|
$('#uploadprogresswrapper .stop').on('click', function() {
|
||||||
OC.Upload.cancelUploads();
|
OC.Upload.cancelUploads();
|
||||||
procesSelection();
|
FileList.updateSelectionSummary();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Show trash bin
|
// Show trash bin
|
||||||
|
@ -217,130 +217,6 @@ $(document).ready(function() {
|
||||||
window.location=OC.filePath('files_trashbin', '', 'index.php');
|
window.location=OC.filePath('files_trashbin', '', 'index.php');
|
||||||
});
|
});
|
||||||
|
|
||||||
var lastChecked;
|
|
||||||
|
|
||||||
// Sets the file link behaviour :
|
|
||||||
$('#fileList').on('click','td.filename a',function(event) {
|
|
||||||
if (event.ctrlKey || event.shiftKey) {
|
|
||||||
event.preventDefault();
|
|
||||||
if (event.shiftKey) {
|
|
||||||
var last = $(lastChecked).parent().parent().prevAll().length;
|
|
||||||
var first = $(this).parent().parent().prevAll().length;
|
|
||||||
var start = Math.min(first, last);
|
|
||||||
var end = Math.max(first, last);
|
|
||||||
var rows = $(this).parent().parent().parent().children('tr');
|
|
||||||
for (var i = start; i < end; i++) {
|
|
||||||
$(rows).each(function(index) {
|
|
||||||
if (index === i) {
|
|
||||||
var checkbox = $(this).children().children('input:checkbox');
|
|
||||||
$(checkbox).attr('checked', 'checked');
|
|
||||||
$(checkbox).parent().parent().addClass('selected');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var checkbox = $(this).parent().children('input:checkbox');
|
|
||||||
lastChecked = checkbox;
|
|
||||||
if ($(checkbox).attr('checked')) {
|
|
||||||
$(checkbox).removeAttr('checked');
|
|
||||||
$(checkbox).parent().parent().removeClass('selected');
|
|
||||||
$('#select_all').removeAttr('checked');
|
|
||||||
} else {
|
|
||||||
$(checkbox).attr('checked', 'checked');
|
|
||||||
$(checkbox).parent().parent().toggleClass('selected');
|
|
||||||
var selectedCount = $('td.filename input:checkbox:checked').length;
|
|
||||||
if (selectedCount === $('td.filename input:checkbox').length) {
|
|
||||||
$('#select_all').attr('checked', 'checked');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
procesSelection();
|
|
||||||
} else {
|
|
||||||
var filename=$(this).parent().parent().attr('data-file');
|
|
||||||
var tr = FileList.findFileEl(filename);
|
|
||||||
var renaming=tr.data('renaming');
|
|
||||||
if (!renaming) {
|
|
||||||
FileActions.currentFile = $(this).parent();
|
|
||||||
var mime=FileActions.getCurrentMimeType();
|
|
||||||
var type=FileActions.getCurrentType();
|
|
||||||
var permissions = FileActions.getCurrentPermissions();
|
|
||||||
var action=FileActions.getDefault(mime,type, permissions);
|
|
||||||
if (action) {
|
|
||||||
event.preventDefault();
|
|
||||||
action(filename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
// Sets the select_all checkbox behaviour :
|
|
||||||
$('#select_all').click(function() {
|
|
||||||
if ($(this).attr('checked')) {
|
|
||||||
// Check all
|
|
||||||
$('td.filename input:checkbox').attr('checked', true);
|
|
||||||
$('td.filename input:checkbox').parent().parent().addClass('selected');
|
|
||||||
} else {
|
|
||||||
// Uncheck all
|
|
||||||
$('td.filename input:checkbox').attr('checked', false);
|
|
||||||
$('td.filename input:checkbox').parent().parent().removeClass('selected');
|
|
||||||
}
|
|
||||||
procesSelection();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#fileList').on('change', 'td.filename input:checkbox',function(event) {
|
|
||||||
if (event.shiftKey) {
|
|
||||||
var last = $(lastChecked).parent().parent().prevAll().length;
|
|
||||||
var first = $(this).parent().parent().prevAll().length;
|
|
||||||
var start = Math.min(first, last);
|
|
||||||
var end = Math.max(first, last);
|
|
||||||
var rows = $(this).parent().parent().parent().children('tr');
|
|
||||||
for (var i = start; i < end; i++) {
|
|
||||||
$(rows).each(function(index) {
|
|
||||||
if (index === i) {
|
|
||||||
var checkbox = $(this).children().children('input:checkbox');
|
|
||||||
$(checkbox).attr('checked', 'checked');
|
|
||||||
$(checkbox).parent().parent().addClass('selected');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var selectedCount=$('td.filename input:checkbox:checked').length;
|
|
||||||
$(this).parent().parent().toggleClass('selected');
|
|
||||||
if (!$(this).attr('checked')) {
|
|
||||||
$('#select_all').attr('checked',false);
|
|
||||||
} else {
|
|
||||||
if (selectedCount===$('td.filename input:checkbox').length) {
|
|
||||||
$('#select_all').attr('checked',true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
procesSelection();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.download').click('click',function(event) {
|
|
||||||
var files;
|
|
||||||
var dir = FileList.getCurrentDirectory();
|
|
||||||
if (FileList.isAllSelected()) {
|
|
||||||
files = OC.basename(dir);
|
|
||||||
dir = OC.dirname(dir) || '/';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
files = Files.getSelectedFiles('name');
|
|
||||||
}
|
|
||||||
OC.Notification.show(t('files','Your download is being prepared. This might take some time if the files are big.'));
|
|
||||||
OC.redirect(Files.getDownloadUrl(files, dir));
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.delete-selected').click(function(event) {
|
|
||||||
var files = Files.getSelectedFiles('name');
|
|
||||||
event.preventDefault();
|
|
||||||
if (FileList.isAllSelected()) {
|
|
||||||
files = null;
|
|
||||||
}
|
|
||||||
FileList.do_delete(files);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
// drag&drop support using jquery.fileupload
|
// drag&drop support using jquery.fileupload
|
||||||
// TODO use OC.dialogs
|
// TODO use OC.dialogs
|
||||||
$(document).bind('drop dragover', function (e) {
|
$(document).bind('drop dragover', function (e) {
|
||||||
|
@ -440,7 +316,7 @@ var createDragShadow = function(event) {
|
||||||
$(event.target).parents('tr').find('td input:first').prop('checked',true);
|
$(event.target).parents('tr').find('td input:first').prop('checked',true);
|
||||||
}
|
}
|
||||||
|
|
||||||
var selectedFiles = Files.getSelectedFiles();
|
var selectedFiles = FileList.getSelectedFiles();
|
||||||
|
|
||||||
if (!isDragSelected && selectedFiles.length === 1) {
|
if (!isDragSelected && selectedFiles.length === 1) {
|
||||||
//revert the selection
|
//revert the selection
|
||||||
|
@ -539,7 +415,7 @@ var folderDropOptions={
|
||||||
oldFile.find('td.filesize').text(humanFileSize(newSize));
|
oldFile.find('td.filesize').text(humanFileSize(newSize));
|
||||||
|
|
||||||
FileList.remove(file);
|
FileList.remove(file);
|
||||||
procesSelection();
|
FileList.updateSelectionSummary();
|
||||||
$('#notification').hide();
|
$('#notification').hide();
|
||||||
} else {
|
} else {
|
||||||
$('#notification').hide();
|
$('#notification').hide();
|
||||||
|
@ -556,78 +432,6 @@ var folderDropOptions={
|
||||||
tolerance: 'pointer'
|
tolerance: 'pointer'
|
||||||
};
|
};
|
||||||
|
|
||||||
function procesSelection() {
|
|
||||||
var selected = Files.getSelectedFiles();
|
|
||||||
var selectedFiles = selected.filter(function(el) {
|
|
||||||
return el.type==='file';
|
|
||||||
});
|
|
||||||
var selectedFolders = selected.filter(function(el) {
|
|
||||||
return el.type==='dir';
|
|
||||||
});
|
|
||||||
if (selectedFiles.length === 0 && selectedFolders.length === 0) {
|
|
||||||
$('#headerName span.name').text(t('files','Name'));
|
|
||||||
$('#headerSize').text(t('files','Size'));
|
|
||||||
$('#modified').text(t('files','Modified'));
|
|
||||||
$('table').removeClass('multiselect');
|
|
||||||
$('.selectedActions').hide();
|
|
||||||
$('#select_all').removeAttr('checked');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$('.selectedActions').show();
|
|
||||||
var totalSize = 0;
|
|
||||||
for(var i=0; i<selectedFiles.length; i++) {
|
|
||||||
totalSize+=selectedFiles[i].size;
|
|
||||||
}
|
|
||||||
for(var i=0; i<selectedFolders.length; i++) {
|
|
||||||
totalSize+=selectedFolders[i].size;
|
|
||||||
}
|
|
||||||
$('#headerSize').text(humanFileSize(totalSize));
|
|
||||||
var selection = '';
|
|
||||||
if (selectedFolders.length > 0) {
|
|
||||||
selection += n('files', '%n folder', '%n folders', selectedFolders.length);
|
|
||||||
if (selectedFiles.length > 0) {
|
|
||||||
selection += ' & ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (selectedFiles.length>0) {
|
|
||||||
selection += n('files', '%n file', '%n files', selectedFiles.length);
|
|
||||||
}
|
|
||||||
$('#headerName span.name').text(selection);
|
|
||||||
$('#modified').text('');
|
|
||||||
$('table').addClass('multiselect');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief get a list of selected files
|
|
||||||
* @param {string} property (option) the property of the file requested
|
|
||||||
* @return {array}
|
|
||||||
*
|
|
||||||
* possible values for property: name, mime, size and type
|
|
||||||
* if property is set, an array with that property for each file is returnd
|
|
||||||
* if it's ommited an array of objects with all properties is returned
|
|
||||||
*/
|
|
||||||
Files.getSelectedFiles = function(property) {
|
|
||||||
var elements=$('td.filename input:checkbox:checked').parent().parent();
|
|
||||||
var files=[];
|
|
||||||
elements.each(function(i,element) {
|
|
||||||
var file={
|
|
||||||
name:$(element).attr('data-file'),
|
|
||||||
mime:$(element).data('mime'),
|
|
||||||
type:$(element).data('type'),
|
|
||||||
size:$(element).data('size'),
|
|
||||||
etag:$(element).data('etag'),
|
|
||||||
origin: $(element).data('id')
|
|
||||||
};
|
|
||||||
if (property) {
|
|
||||||
files.push(file[property]);
|
|
||||||
} else {
|
|
||||||
files.push(file);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
Files.getMimeIcon = function(mime, ready) {
|
Files.getMimeIcon = function(mime, ready) {
|
||||||
if (Files.getMimeIcon.cache[mime]) {
|
if (Files.getMimeIcon.cache[mime]) {
|
||||||
ready(Files.getMimeIcon.cache[mime]);
|
ready(Files.getMimeIcon.cache[mime]);
|
||||||
|
|
|
@ -48,8 +48,15 @@ describe('FileList tests', function() {
|
||||||
' <div class="notCreatable"></div>' +
|
' <div class="notCreatable"></div>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
// dummy table
|
// dummy table
|
||||||
|
// TODO: at some point this will be rendered by the FileList class itself!
|
||||||
'<table id="filestable">' +
|
'<table id="filestable">' +
|
||||||
'<thead><tr><th class="hidden">Name</th></tr></thead>' +
|
'<thead><tr><th id="headerName" class="hidden">' +
|
||||||
|
'<input type="checkbox" id="select_all">' +
|
||||||
|
'<span class="name">Name</span>' +
|
||||||
|
'<span class="selectedActions hidden">' +
|
||||||
|
'<a href class="download">Download</a>' +
|
||||||
|
'<a href class="delete-selected">Delete</a></span>' +
|
||||||
|
'</th></tr></thead>' +
|
||||||
'<tbody id="fileList"></tbody>' +
|
'<tbody id="fileList"></tbody>' +
|
||||||
'<tfoot></tfoot>' +
|
'<tfoot></tfoot>' +
|
||||||
'</table>' +
|
'</table>' +
|
||||||
|
@ -61,25 +68,29 @@ describe('FileList tests', function() {
|
||||||
type: 'file',
|
type: 'file',
|
||||||
name: 'One.txt',
|
name: 'One.txt',
|
||||||
mimetype: 'text/plain',
|
mimetype: 'text/plain',
|
||||||
size: 12
|
size: 12,
|
||||||
|
etag: 'abc'
|
||||||
}, {
|
}, {
|
||||||
id: 2,
|
id: 2,
|
||||||
type: 'file',
|
type: 'file',
|
||||||
name: 'Two.jpg',
|
name: 'Two.jpg',
|
||||||
mimetype: 'image/jpeg',
|
mimetype: 'image/jpeg',
|
||||||
size: 12049
|
size: 12049,
|
||||||
|
etag: 'def',
|
||||||
}, {
|
}, {
|
||||||
id: 3,
|
id: 3,
|
||||||
type: 'file',
|
type: 'file',
|
||||||
name: 'Three.pdf',
|
name: 'Three.pdf',
|
||||||
mimetype: 'application/pdf',
|
mimetype: 'application/pdf',
|
||||||
size: 58009
|
size: 58009,
|
||||||
|
etag: '123',
|
||||||
}, {
|
}, {
|
||||||
id: 4,
|
id: 4,
|
||||||
type: 'dir',
|
type: 'dir',
|
||||||
name: 'somedir',
|
name: 'somedir',
|
||||||
mimetype: 'httpd/unix-directory',
|
mimetype: 'httpd/unix-directory',
|
||||||
size: 250
|
size: 250,
|
||||||
|
etag: '456'
|
||||||
}];
|
}];
|
||||||
|
|
||||||
FileList.initialize();
|
FileList.initialize();
|
||||||
|
@ -380,7 +391,7 @@ describe('FileList tests', function() {
|
||||||
$input.val('One_renamed.txt').blur();
|
$input.val('One_renamed.txt').blur();
|
||||||
|
|
||||||
expect(fakeServer.requests.length).toEqual(1);
|
expect(fakeServer.requests.length).toEqual(1);
|
||||||
var request = fakeServer.requests[0];
|
request = fakeServer.requests[0];
|
||||||
expect(request.url.substr(0, request.url.indexOf('?'))).toEqual(OC.webroot + '/index.php/apps/files/ajax/rename.php');
|
expect(request.url.substr(0, request.url.indexOf('?'))).toEqual(OC.webroot + '/index.php/apps/files/ajax/rename.php');
|
||||||
expect(OC.parseQueryString(request.url)).toEqual({'dir': '/subdir', newname: 'One_renamed.txt', file: 'One.txt'});
|
expect(OC.parseQueryString(request.url)).toEqual({'dir': '/subdir', newname: 'One_renamed.txt', file: 'One.txt'});
|
||||||
|
|
||||||
|
@ -519,6 +530,16 @@ describe('FileList tests', function() {
|
||||||
FileList.setFiles(testFiles);
|
FileList.setFiles(testFiles);
|
||||||
expect(handler.calledOnce).toEqual(true);
|
expect(handler.calledOnce).toEqual(true);
|
||||||
});
|
});
|
||||||
|
it('does not update summary when removing non-existing files', function() {
|
||||||
|
// single file
|
||||||
|
FileList.setFiles([testFiles[0]]);
|
||||||
|
$summary = $('#filestable .summary');
|
||||||
|
expect($summary.hasClass('hidden')).toEqual(false);
|
||||||
|
expect($summary.find('.info').text()).toEqual('0 folders and 1 file');
|
||||||
|
FileList.remove('unexist.txt');
|
||||||
|
expect($summary.hasClass('hidden')).toEqual(false);
|
||||||
|
expect($summary.find('.info').text()).toEqual('0 folders and 1 file');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
describe('file previews', function() {
|
describe('file previews', function() {
|
||||||
var previewLoadStub;
|
var previewLoadStub;
|
||||||
|
@ -811,4 +832,188 @@ describe('FileList tests', function() {
|
||||||
expect(Files.getAjaxUrl('test', {a:1, b:'x y'})).toEqual(OC.webroot + '/index.php/apps/files/ajax/test.php?a=1&b=x%20y');
|
expect(Files.getAjaxUrl('test', {a:1, b:'x y'})).toEqual(OC.webroot + '/index.php/apps/files/ajax/test.php?a=1&b=x%20y');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
describe('File selection', function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
FileList.setFiles(testFiles);
|
||||||
|
});
|
||||||
|
it('Selects a file when clicking its checkbox', function() {
|
||||||
|
var $tr = FileList.findFileEl('One.txt');
|
||||||
|
expect($tr.find('input:checkbox').prop('checked')).toEqual(false);
|
||||||
|
$tr.find('td.filename input:checkbox').click();
|
||||||
|
|
||||||
|
expect($tr.find('input:checkbox').prop('checked')).toEqual(true);
|
||||||
|
});
|
||||||
|
it('Selecting all files will automatically check "select all" checkbox', function() {
|
||||||
|
expect($('#select_all').prop('checked')).toEqual(false);
|
||||||
|
$('#fileList tr td.filename input:checkbox').click();
|
||||||
|
expect($('#select_all').prop('checked')).toEqual(true);
|
||||||
|
});
|
||||||
|
it('Clicking "select all" will select/deselect all files', function() {
|
||||||
|
$('#select_all').click();
|
||||||
|
expect($('#select_all').prop('checked')).toEqual(true);
|
||||||
|
$('#fileList tr input:checkbox').each(function() {
|
||||||
|
expect($(this).prop('checked')).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#select_all').click();
|
||||||
|
expect($('#select_all').prop('checked')).toEqual(false);
|
||||||
|
|
||||||
|
$('#fileList tr input:checkbox').each(function() {
|
||||||
|
expect($(this).prop('checked')).toEqual(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('Clicking "select all" then deselecting a file will uncheck "select all"', function() {
|
||||||
|
$('#select_all').click();
|
||||||
|
expect($('#select_all').prop('checked')).toEqual(true);
|
||||||
|
|
||||||
|
var $tr = FileList.findFileEl('One.txt');
|
||||||
|
$tr.find('input:checkbox').click();
|
||||||
|
|
||||||
|
expect($('#select_all').prop('checked')).toEqual(false);
|
||||||
|
});
|
||||||
|
it('Selecting files updates selection summary', function() {
|
||||||
|
var $summary = $('#headerName span.name');
|
||||||
|
expect($summary.text()).toEqual('Name');
|
||||||
|
FileList.findFileEl('One.txt').find('input:checkbox').click();
|
||||||
|
FileList.findFileEl('Three.pdf').find('input:checkbox').click();
|
||||||
|
FileList.findFileEl('somedir').find('input:checkbox').click();
|
||||||
|
expect($summary.text()).toEqual('1 folder & 2 files');
|
||||||
|
});
|
||||||
|
it('Unselecting files hides selection summary', function() {
|
||||||
|
var $summary = $('#headerName span.name');
|
||||||
|
FileList.findFileEl('One.txt').find('input:checkbox').click().click();
|
||||||
|
expect($summary.text()).toEqual('Name');
|
||||||
|
});
|
||||||
|
it('Select/deselect files shows/hides file actions', function() {
|
||||||
|
var $actions = $('#headerName .selectedActions');
|
||||||
|
var $checkbox = FileList.findFileEl('One.txt').find('input:checkbox');
|
||||||
|
expect($actions.hasClass('hidden')).toEqual(true);
|
||||||
|
$checkbox.click();
|
||||||
|
expect($actions.hasClass('hidden')).toEqual(false);
|
||||||
|
$checkbox.click();
|
||||||
|
expect($actions.hasClass('hidden')).toEqual(true);
|
||||||
|
});
|
||||||
|
it('Selection is cleared when switching dirs', function() {
|
||||||
|
$('#select_all').click();
|
||||||
|
var data = {
|
||||||
|
status: 'success',
|
||||||
|
data: {
|
||||||
|
files: testFiles,
|
||||||
|
permissions: 31
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fakeServer.respondWith(/\/index\.php\/apps\/files\/ajax\/list.php/, [
|
||||||
|
200, {
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
},
|
||||||
|
JSON.stringify(data)
|
||||||
|
]);
|
||||||
|
FileList.changeDirectory('/');
|
||||||
|
fakeServer.respond();
|
||||||
|
expect($('#select_all').prop('checked')).toEqual(false);
|
||||||
|
});
|
||||||
|
describe('Actions', function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
FileList.findFileEl('One.txt').find('input:checkbox').click();
|
||||||
|
FileList.findFileEl('Three.pdf').find('input:checkbox').click();
|
||||||
|
FileList.findFileEl('somedir').find('input:checkbox').click();
|
||||||
|
});
|
||||||
|
it('getSelectedFiles returns the selected files', function() {
|
||||||
|
var files = FileList.getSelectedFiles();
|
||||||
|
expect(files.length).toEqual(3);
|
||||||
|
expect(files[0]).toEqual({
|
||||||
|
id: 1,
|
||||||
|
name: 'One.txt',
|
||||||
|
mime: 'text/plain',
|
||||||
|
mimetype: 'text/plain',
|
||||||
|
type: 'file',
|
||||||
|
size: 12,
|
||||||
|
etag: 'abc',
|
||||||
|
origin: 1
|
||||||
|
});
|
||||||
|
expect(files[1]).toEqual({
|
||||||
|
id: 3,
|
||||||
|
type: 'file',
|
||||||
|
name: 'Three.pdf',
|
||||||
|
mime: 'application/pdf',
|
||||||
|
mimetype: 'application/pdf',
|
||||||
|
size: 58009,
|
||||||
|
etag: '123',
|
||||||
|
origin: 3
|
||||||
|
});
|
||||||
|
expect(files[2]).toEqual({
|
||||||
|
id: 4,
|
||||||
|
type: 'dir',
|
||||||
|
name: 'somedir',
|
||||||
|
mime: 'httpd/unix-directory',
|
||||||
|
mimetype: 'httpd/unix-directory',
|
||||||
|
size: 250,
|
||||||
|
etag: '456',
|
||||||
|
origin: 4
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('Download', function() {
|
||||||
|
it('Opens download URL when clicking "Download"', function() {
|
||||||
|
var redirectStub = sinon.stub(OC, 'redirect');
|
||||||
|
$('.selectedActions .download').click();
|
||||||
|
expect(redirectStub.calledOnce).toEqual(true);
|
||||||
|
expect(redirectStub.getCall(0).args[0]).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=%5B%22One.txt%22%2C%22Three.pdf%22%2C%22somedir%22%5D');
|
||||||
|
redirectStub.restore();
|
||||||
|
});
|
||||||
|
it('Downloads root folder when all selected in root folder', function() {
|
||||||
|
$('#dir').val('/');
|
||||||
|
$('#select_all').click();
|
||||||
|
var redirectStub = sinon.stub(OC, 'redirect');
|
||||||
|
$('.selectedActions .download').click();
|
||||||
|
expect(redirectStub.calledOnce).toEqual(true);
|
||||||
|
expect(redirectStub.getCall(0).args[0]).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2F&files=');
|
||||||
|
redirectStub.restore();
|
||||||
|
});
|
||||||
|
it('Downloads parent folder when all selected in subfolder', function() {
|
||||||
|
$('#select_all').click();
|
||||||
|
var redirectStub = sinon.stub(OC, 'redirect');
|
||||||
|
$('.selectedActions .download').click();
|
||||||
|
expect(redirectStub.calledOnce).toEqual(true);
|
||||||
|
expect(redirectStub.getCall(0).args[0]).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2F&files=subdir');
|
||||||
|
redirectStub.restore();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('Delete', function() {
|
||||||
|
it('Deletes selected files when "Delete" clicked', function() {
|
||||||
|
var request;
|
||||||
|
$('.selectedActions .delete-selected').click();
|
||||||
|
expect(fakeServer.requests.length).toEqual(1);
|
||||||
|
request = fakeServer.requests[0];
|
||||||
|
expect(request.url).toEqual(OC.webroot + '/index.php/apps/files/ajax/delete.php');
|
||||||
|
expect(OC.parseQueryString(request.requestBody))
|
||||||
|
.toEqual({'dir': '/subdir', files: '["One.txt","Three.pdf","somedir"]'});
|
||||||
|
fakeServer.requests[0].respond(
|
||||||
|
200,
|
||||||
|
{ 'Content-Type': 'application/json' },
|
||||||
|
JSON.stringify({status: 'success'})
|
||||||
|
);
|
||||||
|
expect(FileList.findFileEl('One.txt').length).toEqual(0);
|
||||||
|
expect(FileList.findFileEl('Three.pdf').length).toEqual(0);
|
||||||
|
expect(FileList.findFileEl('somedir').length).toEqual(0);
|
||||||
|
expect(FileList.findFileEl('Two.jpg').length).toEqual(1);
|
||||||
|
});
|
||||||
|
it('Deletes all files when all selected when "Delete" clicked', function() {
|
||||||
|
var request;
|
||||||
|
$('#select_all').click();
|
||||||
|
$('.selectedActions .delete-selected').click();
|
||||||
|
expect(fakeServer.requests.length).toEqual(1);
|
||||||
|
request = fakeServer.requests[0];
|
||||||
|
expect(request.url).toEqual(OC.webroot + '/index.php/apps/files/ajax/delete.php');
|
||||||
|
expect(OC.parseQueryString(request.requestBody))
|
||||||
|
.toEqual({'dir': '/subdir', allfiles: 'true'});
|
||||||
|
fakeServer.requests[0].respond(
|
||||||
|
200,
|
||||||
|
{ 'Content-Type': 'application/json' },
|
||||||
|
JSON.stringify({status: 'success'})
|
||||||
|
);
|
||||||
|
expect(FileList.isEmpty).toEqual(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global Files */
|
/* global OC, Files */
|
||||||
describe('Files tests', function() {
|
describe('Files tests', function() {
|
||||||
describe('File name validation', function() {
|
describe('File name validation', function() {
|
||||||
it('Validates correct file names', function() {
|
it('Validates correct file names', function() {
|
||||||
|
@ -82,4 +82,30 @@ describe('Files tests', function() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
describe('getDownloadUrl', function() {
|
||||||
|
var curDirStub;
|
||||||
|
beforeEach(function() {
|
||||||
|
curDirStub = sinon.stub(FileList, 'getCurrentDirectory');
|
||||||
|
});
|
||||||
|
afterEach(function() {
|
||||||
|
curDirStub.restore();
|
||||||
|
});
|
||||||
|
it('returns the ajax download URL when only filename specified', function() {
|
||||||
|
curDirStub.returns('/subdir');
|
||||||
|
var url = Files.getDownloadUrl('test file.txt');
|
||||||
|
expect(url).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=test%20file.txt');
|
||||||
|
});
|
||||||
|
it('returns the ajax download URL when filename and dir specified', function() {
|
||||||
|
var url = Files.getDownloadUrl('test file.txt', '/subdir');
|
||||||
|
expect(url).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=test%20file.txt');
|
||||||
|
});
|
||||||
|
it('returns the ajax download URL when filename and root dir specific', function() {
|
||||||
|
var url = Files.getDownloadUrl('test file.txt', '/');
|
||||||
|
expect(url).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2F&files=test%20file.txt');
|
||||||
|
});
|
||||||
|
it('returns the ajax download URL when multiple files specified', function() {
|
||||||
|
var url = Files.getDownloadUrl(['test file.txt', 'abc.txt'], '/subdir');
|
||||||
|
expect(url).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=%5B%22test%20file.txt%22%2C%22abc.txt%22%5D');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -75,4 +75,130 @@
|
||||||
$('#emptycontent').toggleClass('hidden', exists);
|
$('#emptycontent').toggleClass('hidden', exists);
|
||||||
$('#filestable th').toggleClass('hidden', !exists);
|
$('#filestable th').toggleClass('hidden', !exists);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var oldInit = FileList.initialize;
|
||||||
|
FileList.initialize = function() {
|
||||||
|
var result = oldInit.apply(this, arguments);
|
||||||
|
$('.undelete').click('click', FileList._onClickRestoreSelected);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
FileList._removeCallback = function(result) {
|
||||||
|
if (result.status !== 'success') {
|
||||||
|
OC.dialogs.alert(result.data.message, t('files_trashbin', 'Error'));
|
||||||
|
}
|
||||||
|
|
||||||
|
var files = result.data.success;
|
||||||
|
var $el;
|
||||||
|
for (var i = 0; i < files.length; i++) {
|
||||||
|
$el = FileList.remove(OC.basename(files[i].filename), {updateSummary: false});
|
||||||
|
FileList.fileSummary.remove({type: $el.attr('data-type'), size: $el.attr('data-size')});
|
||||||
|
}
|
||||||
|
FileList.fileSummary.update();
|
||||||
|
FileList.updateEmptyContent();
|
||||||
|
enableActions();
|
||||||
|
}
|
||||||
|
|
||||||
|
FileList._onClickRestoreSelected = function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
var allFiles = $('#select_all').is(':checked');
|
||||||
|
var files = [];
|
||||||
|
var params = {};
|
||||||
|
disableActions();
|
||||||
|
if (allFiles) {
|
||||||
|
FileList.showMask();
|
||||||
|
params = {
|
||||||
|
allfiles: true,
|
||||||
|
dir: FileList.getCurrentDirectory()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
files = FileList.getSelectedFiles('name');
|
||||||
|
for (var i = 0; i < files.length; i++) {
|
||||||
|
var deleteAction = FileList.findFileEl(files[i]).children("td.date").children(".action.delete");
|
||||||
|
deleteAction.removeClass('delete-icon').addClass('progress-icon');
|
||||||
|
}
|
||||||
|
params = {
|
||||||
|
files: JSON.stringify(files),
|
||||||
|
dir: FileList.getCurrentDirectory()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
$.post(OC.filePath('files_trashbin', 'ajax', 'undelete.php'),
|
||||||
|
params,
|
||||||
|
function(result) {
|
||||||
|
if (allFiles) {
|
||||||
|
if (result.status !== 'success') {
|
||||||
|
OC.dialogs.alert(result.data.message, t('files_trashbin', 'Error'));
|
||||||
|
}
|
||||||
|
FileList.hideMask();
|
||||||
|
// simply remove all files
|
||||||
|
FileList.update('');
|
||||||
|
enableActions();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
FileList._removeCallback(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
FileList._onClickDeleteSelected = function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
var allFiles = $('#select_all').is(':checked');
|
||||||
|
var files = [];
|
||||||
|
var params = {};
|
||||||
|
if (allFiles) {
|
||||||
|
params = {
|
||||||
|
allfiles: true,
|
||||||
|
dir: FileList.getCurrentDirectory()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
files = FileList.getSelectedFiles('name');
|
||||||
|
params = {
|
||||||
|
files: JSON.stringify(files),
|
||||||
|
dir: FileList.getCurrentDirectory()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
disableActions();
|
||||||
|
if (allFiles) {
|
||||||
|
FileList.showMask();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (var i = 0; i < files.length; i++) {
|
||||||
|
var deleteAction = FileList.findFileEl(files[i]).children("td.date").children(".action.delete");
|
||||||
|
deleteAction.removeClass('delete-icon').addClass('progress-icon');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$.post(OC.filePath('files_trashbin', 'ajax', 'delete.php'),
|
||||||
|
params,
|
||||||
|
function(result) {
|
||||||
|
if (allFiles) {
|
||||||
|
if (result.status !== 'success') {
|
||||||
|
OC.dialogs.alert(result.data.message, t('files_trashbin', 'Error'));
|
||||||
|
}
|
||||||
|
FileList.hideMask();
|
||||||
|
// simply remove all files
|
||||||
|
FileList.setFiles([]);
|
||||||
|
enableActions();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
FileList._removeCallback(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
var oldClickFile = FileList._onClickFile;
|
||||||
|
FileList._onClickFile = function(event) {
|
||||||
|
var mime = $(this).parent().parent().data('mime');
|
||||||
|
if (mime !== 'httpd/unix-directory') {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
return oldClickFile.apply(this, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -28,22 +28,6 @@ $(document).ready(function() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeCallback(result) {
|
|
||||||
if (result.status !== 'success') {
|
|
||||||
OC.dialogs.alert(result.data.message, t('files_trashbin', 'Error'));
|
|
||||||
}
|
|
||||||
|
|
||||||
var files = result.data.success;
|
|
||||||
var $el;
|
|
||||||
for (var i = 0; i < files.length; i++) {
|
|
||||||
$el = FileList.remove(OC.basename(files[i].filename), {updateSummary: false});
|
|
||||||
FileList.fileSummary.remove({type: $el.attr('data-type'), size: $el.attr('data-size')});
|
|
||||||
}
|
|
||||||
FileList.fileSummary.update();
|
|
||||||
FileList.updateEmptyContent();
|
|
||||||
enableActions();
|
|
||||||
}
|
|
||||||
|
|
||||||
Files.updateStorageStatistics = function() {
|
Files.updateStorageStatistics = function() {
|
||||||
// no op because the trashbin doesn't have
|
// no op because the trashbin doesn't have
|
||||||
// storage info like free space / used space
|
// storage info like free space / used space
|
||||||
|
@ -59,7 +43,7 @@ $(document).ready(function() {
|
||||||
files: JSON.stringify([filename]),
|
files: JSON.stringify([filename]),
|
||||||
dir: FileList.getCurrentDirectory()
|
dir: FileList.getCurrentDirectory()
|
||||||
},
|
},
|
||||||
removeCallback
|
FileList._removeCallback
|
||||||
);
|
);
|
||||||
}, t('files_trashbin', 'Restore'));
|
}, t('files_trashbin', 'Restore'));
|
||||||
};
|
};
|
||||||
|
@ -76,153 +60,10 @@ $(document).ready(function() {
|
||||||
files: JSON.stringify([filename]),
|
files: JSON.stringify([filename]),
|
||||||
dir: FileList.getCurrentDirectory()
|
dir: FileList.getCurrentDirectory()
|
||||||
},
|
},
|
||||||
removeCallback
|
FileList._removeCallback
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Sets the select_all checkbox behaviour :
|
|
||||||
$('#select_all').click(function() {
|
|
||||||
if ($(this).attr('checked')) {
|
|
||||||
// Check all
|
|
||||||
$('td.filename input:checkbox').attr('checked', true);
|
|
||||||
$('td.filename input:checkbox').parent().parent().addClass('selected');
|
|
||||||
} else {
|
|
||||||
// Uncheck all
|
|
||||||
$('td.filename input:checkbox').attr('checked', false);
|
|
||||||
$('td.filename input:checkbox').parent().parent().removeClass('selected');
|
|
||||||
}
|
|
||||||
procesSelection();
|
|
||||||
});
|
|
||||||
$('.undelete').click('click', function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
var allFiles = $('#select_all').is(':checked');
|
|
||||||
var files = [];
|
|
||||||
var params = {};
|
|
||||||
disableActions();
|
|
||||||
if (allFiles) {
|
|
||||||
FileList.showMask();
|
|
||||||
params = {
|
|
||||||
allfiles: true,
|
|
||||||
dir: FileList.getCurrentDirectory()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
files = Files.getSelectedFiles('name');
|
|
||||||
for (var i = 0; i < files.length; i++) {
|
|
||||||
var deleteAction = FileList.findFileEl(files[i]).children("td.date").children(".action.delete");
|
|
||||||
deleteAction.removeClass('delete-icon').addClass('progress-icon');
|
|
||||||
}
|
|
||||||
params = {
|
|
||||||
files: JSON.stringify(files),
|
|
||||||
dir: FileList.getCurrentDirectory()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
$.post(OC.filePath('files_trashbin', 'ajax', 'undelete.php'),
|
|
||||||
params,
|
|
||||||
function(result) {
|
|
||||||
if (allFiles) {
|
|
||||||
if (result.status !== 'success') {
|
|
||||||
OC.dialogs.alert(result.data.message, t('files_trashbin', 'Error'));
|
|
||||||
}
|
|
||||||
FileList.hideMask();
|
|
||||||
// simply remove all files
|
|
||||||
FileList.update('');
|
|
||||||
enableActions();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
removeCallback(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.delete').click('click', function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
var allFiles = $('#select_all').is(':checked');
|
|
||||||
var files = [];
|
|
||||||
var params = {};
|
|
||||||
if (allFiles) {
|
|
||||||
params = {
|
|
||||||
allfiles: true,
|
|
||||||
dir: FileList.getCurrentDirectory()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
files = Files.getSelectedFiles('name');
|
|
||||||
params = {
|
|
||||||
files: JSON.stringify(files),
|
|
||||||
dir: FileList.getCurrentDirectory()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
disableActions();
|
|
||||||
if (allFiles) {
|
|
||||||
FileList.showMask();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (var i = 0; i < files.length; i++) {
|
|
||||||
var deleteAction = FileList.findFileEl(files[i]).children("td.date").children(".action.delete");
|
|
||||||
deleteAction.removeClass('delete-icon').addClass('progress-icon');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$.post(OC.filePath('files_trashbin', 'ajax', 'delete.php'),
|
|
||||||
params,
|
|
||||||
function(result) {
|
|
||||||
if (allFiles) {
|
|
||||||
if (result.status !== 'success') {
|
|
||||||
OC.dialogs.alert(result.data.message, t('files_trashbin', 'Error'));
|
|
||||||
}
|
|
||||||
FileList.hideMask();
|
|
||||||
// simply remove all files
|
|
||||||
FileList.setFiles([]);
|
|
||||||
enableActions();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
removeCallback(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#fileList').on('click', 'td.filename input', function() {
|
|
||||||
var checkbox = $(this).parent().children('input:checkbox');
|
|
||||||
$(checkbox).parent().parent().toggleClass('selected');
|
|
||||||
if ($(checkbox).is(':checked')) {
|
|
||||||
var selectedCount = $('td.filename input:checkbox:checked').length;
|
|
||||||
if (selectedCount === $('td.filename input:checkbox').length) {
|
|
||||||
$('#select_all').prop('checked', true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$('#select_all').prop('checked',false);
|
|
||||||
}
|
|
||||||
procesSelection();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#fileList').on('click', 'td.filename a', function(event) {
|
|
||||||
var mime = $(this).parent().parent().data('mime');
|
|
||||||
if (mime !== 'httpd/unix-directory') {
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
var filename = $(this).parent().parent().attr('data-file');
|
|
||||||
var tr = FileList.findFileEl(filename);
|
|
||||||
var renaming = tr.data('renaming');
|
|
||||||
if(!renaming){
|
|
||||||
if(mime.substr(0, 5) === 'text/'){ //no texteditor for now
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var type = $(this).parent().parent().data('type');
|
|
||||||
var permissions = $(this).parent().parent().data('permissions');
|
|
||||||
var action = FileActions.getDefault(mime, type, permissions);
|
|
||||||
if(action){
|
|
||||||
event.preventDefault();
|
|
||||||
action(filename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override crumb URL maker (hacky!)
|
* Override crumb URL maker (hacky!)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1250,7 +1250,7 @@ function relative_modified_date(timestamp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @todo Write documentation
|
* Utility functions
|
||||||
*/
|
*/
|
||||||
OC.Util = {
|
OC.Util = {
|
||||||
// TODO: remove original functions from global namespace
|
// TODO: remove original functions from global namespace
|
||||||
|
|
Loading…
Reference in New Issue