diff options
Diffstat (limited to 'apps/files/js/files.js')
-rw-r--r-- | apps/files/js/files.js | 273 |
1 files changed, 195 insertions, 78 deletions
diff --git a/apps/files/js/files.js b/apps/files/js/files.js index 0b10fa8c63a..1ec4c4ec7ab 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -1,10 +1,59 @@ -Files={ +/* + * Copyright (c) 2014 + * + * This file is licensed under the Affero General Public License version 3 + * or later. + * + * See the COPYING-README file. + * + */ + +/* global OC, t, n, FileList, FileActions */ +/* global getURLParameter, isPublic */ +var Files = { + // file space size sync + _updateStorageStatistics: function() { + Files._updateStorageStatisticsTimeout = null; + var currentDir = FileList.getCurrentDirectory(), + state = Files.updateStorageStatistics; + if (state.dir){ + if (state.dir === currentDir) { + return; + } + // cancel previous call, as it was for another dir + state.call.abort(); + } + state.dir = currentDir; + state.call = $.getJSON(OC.filePath('files','ajax','getstoragestats.php') + '?dir=' + encodeURIComponent(currentDir),function(response) { + state.dir = null; + state.call = null; + Files.updateMaxUploadFilesize(response); + }); + }, + updateStorageStatistics: function(force) { + if (!OC.currentUser) { + return; + } + + // debounce to prevent calling too often + if (Files._updateStorageStatisticsTimeout) { + clearTimeout(Files._updateStorageStatisticsTimeout); + } + if (force) { + Files._updateStorageStatistics(); + } + else { + Files._updateStorageStatisticsTimeout = setTimeout(Files._updateStorageStatistics, 250); + } + }, + updateMaxUploadFilesize:function(response) { if (response === undefined) { return; } if (response.data !== undefined && response.data.uploadMaxFilesize !== undefined) { $('#max_upload').val(response.data.uploadMaxFilesize); + $('#free_space').val(response.data.freeSpace); $('#upload.button').attr('original-title', response.data.maxHumanFilesize); $('#usedSpacePercent').val(response.data.usedSpacePercent); Files.displayStorageWarnings(); @@ -20,17 +69,36 @@ Files={ } }, - isFileNameValid:function (name) { - if (name === '.') { - throw t('files', '\'.\' is an invalid file name.'); - } else if (name.length === 0) { - throw t('files', 'File name cannot be empty.'); + + /** + * Fix path name by removing double slash at the beginning, if any + */ + fixPath: function(fileName) { + if (fileName.substr(0, 2) == '//') { + return fileName.substr(1); } + return fileName; + }, + /** + * Checks whether the given file name is valid. + * @param name file name to check + * @return true if the file name is valid. + * Throws a string exception with an error message if + * the file name is not valid + */ + isFileNameValid: function (name) { + var trimmedName = name.trim(); + if (trimmedName === '.' || trimmedName === '..') { + throw t('files', '"{name}" is an invalid file name.', {name: name}); + } else if (trimmedName.length === 0) { + throw t('files', 'File name cannot be empty.'); + } // check for invalid characters - var invalid_characters = ['\\', '/', '<', '>', ':', '"', '|', '?', '*']; + var invalid_characters = + ['\\', '/', '<', '>', ':', '"', '|', '?', '*', '\n']; for (var i = 0; i < invalid_characters.length; i++) { - if (name.indexOf(invalid_characters[i]) !== -1) { + if (trimmedName.indexOf(invalid_characters[i]) !== -1) { throw t('files', "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed."); } } @@ -235,7 +303,7 @@ $(document).ready(function() { procesSelection(); } else { var filename=$(this).parent().parent().attr('data-file'); - var tr=$('tr[data-file="'+filename+'"]'); + var tr = FileList.findFileEl(filename); var renaming=tr.data('renaming'); if (!renaming && !FileList.isLoading(filename)) { FileActions.currentFile = $(this).parent(); @@ -337,33 +405,29 @@ $(document).ready(function() { Files.resizeBreadcrumbs(width, true); // display storage warnings - setTimeout ( "Files.displayStorageWarnings()", 100 ); + setTimeout(Files.displayStorageWarnings, 100); OC.Notification.setDefault(Files.displayStorageWarnings); - // file space size sync - function update_storage_statistics() { - $.getJSON(OC.filePath('files','ajax','getstoragestats.php'),function(response) { - Files.updateMaxUploadFilesize(response); - }); - } - - // start on load - we ask the server every 5 minutes - var update_storage_statistics_interval = 5*60*1000; - var update_storage_statistics_interval_id = setInterval(update_storage_statistics, update_storage_statistics_interval); - - // Use jquery-visibility to de-/re-activate file stats sync - if ($.support.pageVisibility) { - $(document).on({ - 'show.visibility': function() { - if (!update_storage_statistics_interval_id) { - update_storage_statistics_interval_id = setInterval(update_storage_statistics, update_storage_statistics_interval); + // only possible at the moment if user is logged in + if (OC.currentUser) { + // start on load - we ask the server every 5 minutes + var updateStorageStatisticsInterval = 5*60*1000; + var updateStorageStatisticsIntervalId = setInterval(Files.updateStorageStatistics, updateStorageStatisticsInterval); + + // Use jquery-visibility to de-/re-activate file stats sync + if ($.support.pageVisibility) { + $(document).on({ + 'show.visibility': function() { + if (!updateStorageStatisticsIntervalId) { + updateStorageStatisticsIntervalId = setInterval(Files.updateStorageStatistics, updateStorageStatisticsInterval); + } + }, + 'hide.visibility': function() { + clearInterval(updateStorageStatisticsIntervalId); + updateStorageStatisticsIntervalId = 0; } - }, - 'hide.visibility': function() { - clearInterval(update_storage_statistics_interval_id); - update_storage_statistics_interval_id = 0; - } - }); + }); + } } //scroll to and highlight preselected file @@ -404,6 +468,7 @@ function scanFiles(force, dir, users) { scannerEventSource.listen('done',function(count) { scanFiles.scanning=false; console.log('done after ' + count + ' files'); + Files.updateStorageStatistics(); }); scannerEventSource.listen('user',function(user) { console.log('scanning files for ' + user); @@ -449,7 +514,7 @@ var createDragShadow = function(event) { var dir=$('#dir').val(); $(selectedFiles).each(function(i,elem) { - var newtr = $('<tr/>').attr('data-dir', dir).attr('data-filename', elem.name); + var newtr = $('<tr/>').attr('data-dir', dir).attr('data-filename', elem.name).attr('data-origin', elem.origin); newtr.append($('<td/>').addClass('filename').text(elem.name)); newtr.append($('<td/>').addClass('size').text(humanFileSize(elem.size))); tbody.append(newtr); @@ -457,9 +522,9 @@ var createDragShadow = function(event) { newtr.find('td.filename').attr('style','background-image:url('+OC.imagePath('core', 'filetypes/folder.png')+')'); } else { var path = getPathForPreview(elem.name); - lazyLoadPreview(path, elem.mime, function(previewpath) { + Files.lazyLoadPreview(path, elem.mime, function(previewpath) { newtr.find('td.filename').attr('style','background-image:url('+previewpath+')'); - }); + }, null, null, elem.etag); } }); @@ -467,13 +532,30 @@ var createDragShadow = function(event) { }; //options for file drag/drop +//start&stop handlers needs some cleaning up var dragOptions={ revert: 'invalid', revertDuration: 300, - opacity: 0.7, zIndex: 100, appendTo: 'body', cursorAt: { left: -5, top: -5 }, + opacity: 0.7, zIndex: 100, appendTo: 'body', cursorAt: { left: 24, top: 18 }, helper: createDragShadow, cursor: 'move', - stop: function(event, ui) { - $('#fileList tr td.filename').addClass('ui-draggable'); - } + start: function(event, ui){ + var $selectedFiles = $('td.filename input:checkbox:checked'); + if($selectedFiles.length > 1){ + $selectedFiles.parents('tr').fadeTo(250, 0.2); + } + else{ + $(this).fadeTo(250, 0.2); + } + }, + stop: function(event, ui) { + var $selectedFiles = $('td.filename input:checkbox:checked'); + if($selectedFiles.length > 1){ + $selectedFiles.parents('tr').fadeTo(250, 1); + } + else{ + $(this).fadeTo(250, 1); + } + $('#fileList tr td.filename').addClass('ui-draggable'); + } }; // sane browsers support using the distance option if ( $('html.ie').length === 0) { @@ -481,6 +563,7 @@ if ( $('html.ie').length === 0) { } var folderDropOptions={ + hoverClass: "canDrop", drop: function( event, ui ) { //don't allow moving a file into a selected folder if ($(event.target).parents('tr').find('td input:first').prop('checked') === true) { @@ -493,14 +576,21 @@ var folderDropOptions={ $(files).each(function(i,row) { var dir = $(row).data('dir'); var file = $(row).data('filename'); + //slapdash selector, tracking down our original element that the clone budded off of. + var origin = $('tr[data-id=' + $(row).data('origin') + ']'); + var td = origin.children('td.filename'); + var oldBackgroundImage = td.css('background-image'); + td.css('background-image', 'url('+ OC.imagePath('core', 'loading.gif') + ')'); $.post(OC.filePath('files', 'ajax', 'move.php'), { dir: dir, file: file, target: dir+'/'+target }, function(result) { if (result) { if (result.status === 'success') { //recalculate folder size - var oldSize = $('#fileList tr[data-file="'+target+'"]').data('size'); - var newSize = oldSize + $('#fileList tr[data-file="'+file+'"]').data('size'); - $('#fileList tr[data-file="'+target+'"]').data('size', newSize); - $('#fileList tr[data-file="'+target+'"]').find('td.filesize').text(humanFileSize(newSize)); + var oldFile = FileList.findFileEl(target); + var newFile = FileList.findFileEl(file); + var oldSize = oldFile.data('size'); + var newSize = oldSize + newFile.data('size'); + oldFile.data('size', newSize); + oldFile.find('td.filesize').text(humanFileSize(newSize)); FileList.remove(file); procesSelection(); @@ -513,6 +603,7 @@ var folderDropOptions={ } else { OC.dialogs.alert(t('files', 'Error moving file'), t('files', 'Error')); } + td.css('background-image', oldBackgroundImage); }); }); }, @@ -537,6 +628,11 @@ var crumbDropOptions={ $(files).each(function(i,row) { var dir = $(row).data('dir'); var file = $(row).data('filename'); + //slapdash selector, tracking down our original element that the clone budded off of. + var origin = $('tr[data-id=' + $(row).data('origin') + ']'); + var td = origin.children('td.filename'); + var oldBackgroundImage = td.css('background-image'); + td.css('background-image', 'url('+ OC.imagePath('core', 'loading.gif') + ')'); $.post(OC.filePath('files', 'ajax', 'move.php'), { dir: dir, file: file, target: target }, function(result) { if (result) { if (result.status === 'success') { @@ -551,6 +647,7 @@ var crumbDropOptions={ } else { OC.dialogs.alert(t('files', 'Error moving file'), t('files', 'Error')); } + td.css('background-image', oldBackgroundImage); }); }); }, @@ -566,21 +663,22 @@ function procesSelection() { return el.type==='dir'; }); if (selectedFiles.length === 0 && selectedFolders.length === 0) { - $('#headerName>span.name').text(t('files','Name')); + $('#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) { @@ -592,7 +690,7 @@ function procesSelection() { if (selectedFiles.length>0) { selection += n('files', '%n file', '%n files', selectedFiles.length); } - $('#headerName>span.name').text(selection); + $('#headerName span.name').text(selection); $('#modified').text(''); $('table').addClass('multiselect'); } @@ -615,7 +713,9 @@ function getSelectedFilesTrash(property) { name:$(element).attr('data-file'), mime:$(element).data('mime'), type:$(element).data('type'), - size:$(element).data('size') + size:$(element).data('size'), + etag:$(element).data('etag'), + origin: $(element).data('id') }; if (property) { files.push(file[property]); @@ -626,26 +726,28 @@ function getSelectedFilesTrash(property) { return files; } -function getMimeIcon(mime, ready) { - if (getMimeIcon.cache[mime]) { - ready(getMimeIcon.cache[mime]); +Files.getMimeIcon = function(mime, ready) { + if (Files.getMimeIcon.cache[mime]) { + ready(Files.getMimeIcon.cache[mime]); } else { $.get( OC.filePath('files','ajax','mimeicon.php'), {mime: mime}, function(path) { - getMimeIcon.cache[mime]=path; - ready(getMimeIcon.cache[mime]); + Files.getMimeIcon.cache[mime]=path; + ready(Files.getMimeIcon.cache[mime]); }); } } -getMimeIcon.cache={}; +Files.getMimeIcon.cache={}; function getPathForPreview(name) { var path = $('#dir').val() + '/' + name; return path; } -function lazyLoadPreview(path, mime, ready, width, height) { +Files.lazyLoadPreview = function(path, mime, ready, width, height, etag) { // get mime icon url - getMimeIcon(mime, function(iconURL) { + Files.getMimeIcon(mime, function(iconURL) { + var urlSpec = {}; + var previewURL; ready(iconURL); // set mimeicon URL // now try getting a preview thumbnail URL @@ -655,30 +757,44 @@ function lazyLoadPreview(path, mime, ready, width, height) { if ( ! height ) { height = $('#filestable').data('preview-y'); } - if ( $('#publicUploadButtonMock').length ) { - var previewURL = OC.Router.generate('core_ajax_public_preview', {file: path, x:width, y:height, t:$('#dirToken').val()}); + // note: the order of arguments must match the one + // from the server's template so that the browser + // knows it's the same file for caching + urlSpec.x = width; + urlSpec.y = height; + urlSpec.file = Files.fixPath(path); + + if (etag){ + // use etag as cache buster + urlSpec.c = etag; + } + else { + console.warn('Files.lazyLoadPreview(): missing etag argument'); + } + + if ( $('#isPublic').length ) { + urlSpec.t = $('#dirToken').val(); + previewURL = OC.Router.generate('core_ajax_public_preview', urlSpec); } else { - var previewURL = OC.Router.generate('core_ajax_preview', {file: path, x:width, y:height}); - } - $.get(previewURL, function() { - previewURL = previewURL.replace('(', '%28'); - previewURL = previewURL.replace(')', '%29'); - previewURL += '&reload=true'; - - // preload image to prevent delay - // this will make the browser cache the image - var img = new Image(); - img.onload = function(){ - //set preview thumbnail URL - ready(previewURL); - } - img.src = previewURL; - }); + previewURL = OC.Router.generate('core_ajax_preview', urlSpec); + } + previewURL = previewURL.replace('(', '%28'); + previewURL = previewURL.replace(')', '%29'); + + // preload image to prevent delay + // this will make the browser cache the image + var img = new Image(); + img.onload = function(){ + //set preview thumbnail URL + ready(previewURL); + } + img.src = previewURL; }); -} +}; function getUniqueName(name) { - if ($('tr[data-file="'+name+'"]').exists()) { + if (FileList.findFileEl(name).exists()) { + var numMatch; var parts=name.split('.'); var extension = ""; if (parts.length > 1) { @@ -712,7 +828,7 @@ function checkTrashStatus() { function onClickBreadcrumb(e) { var $el = $(e.target).closest('.crumb'), - $targetDir = $el.data('dir'); + $targetDir = $el.data('dir'), isPublic = !!$('#isPublic').val(); if ($targetDir !== undefined && !isPublic) { @@ -720,3 +836,4 @@ function onClickBreadcrumb(e) { FileList.changeDirectory(decodeURIComponent($targetDir)); } } + |