Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File list sorting by clicking on column headers #8041

Merged
merged 7 commits into from May 12, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion apps/files/ajax/list.php
Expand Up @@ -17,8 +17,11 @@

$permissions = $dirInfo->getPermissions();

$sortAttribute = isset( $_GET['sort'] ) ? $_GET['sort'] : 'name';
$sortDirection = isset( $_GET['sortdirection'] ) ? ($_GET['sortdirection'] === 'desc') : false;

// make filelist
$files = \OCA\Files\Helper::getFiles($dir);
$files = \OCA\Files\Helper::getFiles($dir, $sortAttribute, $sortDirection);

$data['directory'] = $dir;
$data['files'] = \OCA\Files\Helper::formatFileInfos($files);
Expand Down
36 changes: 27 additions & 9 deletions apps/files/css/files.css
Expand Up @@ -116,10 +116,29 @@ tr:hover span.extension {

table tr.mouseOver td { background-color:#eee; }
table th { height:24px; padding:0 8px; color:#999; }
table th .name {
position: absolute;
left: 55px;
top: 15px;
table th .columntitle {
display: inline-block;
padding: 15px;
width: 100%;
height: 50px;
box-sizing: border-box;
-moz-box-sizing: border-box;
vertical-align: middle;
}
table th .columntitle.name {
padding-left: 5px;
margin-left: 50px;
max-width: 300px;
}
/* hover effect on sortable column */
table th a.columntitle:hover {
background-color: #F0F0F0;
}
table th .sort-indicator {
width: 10px;
height: 8px;
margin-left: 10px;
display: inline-block;
}
table th, table td { border-bottom:1px solid #ddd; text-align:left; font-weight:normal; }
table td {
Expand All @@ -139,8 +158,11 @@ table th#headerName {
}
table th#headerSize, table td.filesize {
min-width: 48px;
padding: 0 16px;
text-align: right;
padding: 0;
}
table table td.filesize {
padding: 0 16px;
}
table th#headerDate, table td.date {
-moz-box-sizing: border-box;
Expand Down Expand Up @@ -197,10 +219,6 @@ table td.filename input.filename {
table td.filename a, table td.login, table td.logout, table td.download, table td.upload, table td.create, table td.delete { padding:3px 8px 8px 3px; }
table td.filename .nametext, .uploadtext, .modified { float:left; padding:14px 0; }

#modified {
position: absolute;
top: 15px;
}
.modified {
position: relative;
padding-left: 8px;
Expand Down
143 changes: 121 additions & 22 deletions apps/files/js/filelist.js
Expand Up @@ -11,6 +11,9 @@
/* global OC, t, n, FileList, FileActions, Files, FileSummary, BreadCrumb */
/* global dragOptions, folderDropOptions */
window.FileList = {
SORT_INDICATOR_ASC_CLASS: 'icon-triangle-s',
SORT_INDICATOR_DESC_CLASS: 'icon-triangle-n',

appName: t('files', 'Files'),
isEmpty: true,
useUndo:true,
Expand Down Expand Up @@ -45,18 +48,19 @@ window.FileList = {
_selectionSummary: null,

/**
* Compare two file info objects, sorting by
* folders first, then by name.
* Sort attribute
*/
_fileInfoCompare: function(fileInfo1, fileInfo2) {
if (fileInfo1.type === 'dir' && fileInfo2.type !== 'dir') {
return -1;
}
if (fileInfo1.type !== 'dir' && fileInfo2.type === 'dir') {
return 1;
}
return fileInfo1.name.localeCompare(fileInfo2.name);
},
_sort: 'name',

/**
* Sort direction: 'asc' or 'desc'
*/
_sortDirection: 'asc',

/**
* Sort comparator function for the current sort
*/
_sortComparator: null,

/**
* Initialize the file list and its components
Expand All @@ -76,6 +80,8 @@ window.FileList = {

this.fileSummary = this._createSummary();

this.setSort('name', 'asc');

this.breadcrumb = new BreadCrumb({
onClick: this._onClickBreadCrumb,
onDrop: _.bind(this._onDropOnBreadCrumb, this),
Expand All @@ -86,6 +92,8 @@ window.FileList = {

$('#controls').prepend(this.breadcrumb.$el);

this.$el.find('thead th .columntitle').click(_.bind(this._onClickHeader, this));

$(window).resize(function() {
// TODO: debounce this ?
var width = $(this).width();
Expand Down Expand Up @@ -236,6 +244,27 @@ window.FileList = {
return false;
},

/**
* Event handler when clicking on a table header
*/
_onClickHeader: function(e) {
var $target = $(e.target);
var sort;
if (!$target.is('a')) {
$target = $target.closest('a');
}
sort = $target.attr('data-sort');
if (sort) {
if (this._sort === sort) {
this.setSort(sort, (this._sortDirection === 'desc')?'asc':'desc');
}
else {
this.setSort(sort, 'asc');
}
this.reload();
}
},

/**
* Event handler when clicking on a bread crumb
*/
Expand Down Expand Up @@ -685,8 +714,6 @@ window.FileList = {
previousDir: currentDir
}
));
this._selectedFiles = {};
this._selectionSummary.clear();
this.reload();
},
linkTo: function(dir) {
Expand Down Expand Up @@ -722,18 +749,44 @@ window.FileList = {
}
this.breadcrumb.setDirectory(this.getCurrentDirectory());
},
/**
* Sets the current sorting and refreshes the list
*
* @param sort sort attribute name
* @param direction sort direction, one of "asc" or "desc"
*/
setSort: function(sort, direction) {
var comparator = this.Comparators[sort] || this.Comparators.name;
this._sort = sort;
this._sortDirection = (direction === 'desc')?'desc':'asc';
this._sortComparator = comparator;
if (direction === 'desc') {
this._sortComparator = function(fileInfo1, fileInfo2) {
return -comparator(fileInfo1, fileInfo2);
};
}
this.$el.find('thead th .sort-indicator')
.removeClass(this.SORT_INDICATOR_ASC_CLASS + ' ' + this.SORT_INDICATOR_DESC_CLASS);
this.$el.find('thead th.column-' + sort + ' .sort-indicator')
.addClass(direction === 'desc' ? this.SORT_INDICATOR_DESC_CLASS : this.SORT_INDICATOR_ASC_CLASS);
},
/**
* @brief Reloads the file list using ajax call
*/
reload: function() {
this._selectedFiles = {};
this._selectionSummary.clear();
this.$el.find('#select_all').prop('checked', false);
FileList.showMask();
if (FileList._reloadCall) {
FileList._reloadCall.abort();
}
FileList._reloadCall = $.ajax({
url: Files.getAjaxUrl('list'),
data: {
dir : $('#dir').val()
dir: $('#dir').val(),
sort: FileList._sort,
sortdirection: FileList._sortDirection
},
error: function(result) {
FileList.reloadCallback(result);
Expand Down Expand Up @@ -859,7 +912,7 @@ window.FileList = {
*/
_findInsertionIndex: function(fileData) {
var index = 0;
while (index < this.files.length && this._fileInfoCompare(fileData, this.files[index]) > 0) {
while (index < this.files.length && this._sortComparator(fileData, this.files[index]) > 0) {
index++;
}
return index;
Expand Down Expand Up @@ -924,7 +977,7 @@ window.FileList = {
OC.dialogs.alert(t('files', 'Error moving file'), t('files', 'Error'));
}
$td.css('background-image', oldBackgroundImage);
});
});
});

},
Expand Down Expand Up @@ -1218,15 +1271,15 @@ window.FileList = {
updateSelectionSummary: function() {
var summary = this._selectionSummary.summary;
if (summary.totalFiles === 0 && summary.totalDirs === 0) {
$('#headerName span.name').text(t('files','Name'));
$('#headerSize').text(t('files','Size'));
$('#modified').text(t('files','Modified'));
$('#headerName a.name>span:first').text(t('files','Name'));
$('#headerSize a>span:first').text(t('files','Size'));
$('#modified a>span:first').text(t('files','Modified'));
$('table').removeClass('multiselect');
$('.selectedActions').addClass('hidden');
}
else {
$('.selectedActions').removeClass('hidden');
$('#headerSize').text(OC.Util.humanFileSize(summary.totalSize));
$('#headerSize a>span:first').text(OC.Util.humanFileSize(summary.totalSize));
var selection = '';
if (summary.totalDirs > 0) {
selection += n('files', '%n folder', '%n folders', summary.totalDirs);
Expand All @@ -1237,8 +1290,8 @@ window.FileList = {
if (summary.totalFiles > 0) {
selection += n('files', '%n file', '%n files', summary.totalFiles);
}
$('#headerName span.name').text(selection);
$('#modified').text('');
$('#headerName a.name>span:first').text(selection);
$('#modified a>span:first').text('');
$('table').addClass('multiselect');
}
},
Expand Down Expand Up @@ -1542,3 +1595,49 @@ $(document).ready(function() {
}, 0);
});

/**
* Sort comparators.
*/
FileList.Comparators = {
/**
* Compares two file infos by name, making directories appear
* first.
*
* @param fileInfo1 file info
* @param fileInfo2 file info
* @return -1 if the first file must appear before the second one,
* 0 if they are identify, 1 otherwise.
*/
name: function(fileInfo1, fileInfo2) {
if (fileInfo1.type === 'dir' && fileInfo2.type !== 'dir') {
return -1;
}
if (fileInfo1.type !== 'dir' && fileInfo2.type === 'dir') {
return 1;
}
return fileInfo1.name.localeCompare(fileInfo2.name);
},
/**
* Compares two file infos by size.
*
* @param fileInfo1 file info
* @param fileInfo2 file info
* @return -1 if the first file must appear before the second one,
* 0 if they are identify, 1 otherwise.
*/
size: function(fileInfo1, fileInfo2) {
return fileInfo1.size - fileInfo2.size;
},
/**
* Compares two file infos by timestamp.
*
* @param fileInfo1 file info
* @param fileInfo2 file info
* @return -1 if the first file must appear before the second one,
* 0 if they are identify, 1 otherwise.
*/
mtime: function(fileInfo1, fileInfo2) {
return fileInfo1.mtime - fileInfo2.mtime;
}
};