diff options
author | Jörn Friedrich Dreyer <jfd@butonic.de> | 2013-08-22 14:29:00 +0200 |
---|---|---|
committer | Jörn Friedrich Dreyer <jfd@butonic.de> | 2013-08-22 14:29:00 +0200 |
commit | 7c9d9992432839f2265b8f6b0f43ed15bfca9ff1 (patch) | |
tree | e286efb0aedb2c0227e8bac2e30e8c74327832d2 | |
parent | bf04daff82758fe9913c706eef07aed30c9b35ea (diff) | |
download | nextcloud-server-7c9d9992432839f2265b8f6b0f43ed15bfca9ff1.tar.gz nextcloud-server-7c9d9992432839f2265b8f6b0f43ed15bfca9ff1.zip |
reduced complexity, added listing conflicts to dialog
-rw-r--r-- | apps/files/ajax/upload.php | 1 | ||||
-rw-r--r-- | apps/files/css/files.css | 53 | ||||
-rw-r--r-- | apps/files/js/file-upload.js | 226 | ||||
-rw-r--r-- | core/js/oc-dialogs.js | 305 |
4 files changed, 390 insertions, 195 deletions
diff --git a/apps/files/ajax/upload.php b/apps/files/ajax/upload.php index 619b5f6a04b..218482cb41d 100644 --- a/apps/files/ajax/upload.php +++ b/apps/files/ajax/upload.php @@ -131,6 +131,7 @@ if (strpos($dir, '..') === false) { $result[] = array('status' => 'success', 'mime' => $meta['mimetype'], + 'mtime' => $meta['mtime'], 'size' => $meta['size'], 'id' => $meta['fileid'], 'name' => basename($target), diff --git a/apps/files/css/files.css b/apps/files/css/files.css index 0ff25a24d76..dcd6aeadf82 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -193,28 +193,54 @@ table.dragshadow td.size { .oc-dialog .fileexists table { width: 100%; } -.oc-dialog .fileexists .original .icon { +.oc-dialog .fileexists th { + padding-left: 0; + padding-right: 0; +} +.oc-dialog .fileexists th input[type='checkbox'] { + margin-right: 3px; +} +.oc-dialog .fileexists th:first-child { + width: 235px; +} +.oc-dialog .fileexists th label { + font-weight: normal; + color:black; +} +.oc-dialog .fileexists th .count { + margin-left: 3px; +} +.oc-dialog .fileexists .conflict { + width: 100%; + height: 85px; +} +.oc-dialog .fileexists .conflict .filename { + color:#777; + word-break: break-all; +} +.oc-dialog .fileexists .icon { width: 64px; height: 64px; - margin: 5px 5px 5px 0px; + margin: 0px 5px 5px 5px; background-repeat: no-repeat; background-size: 64px 64px; float: left; } .oc-dialog .fileexists .replacement { - margin-top: 20px; - margin-bottom: 20px; + float: left; + width: 235px; } - -.oc-dialog .fileexists .replacement .icon { - width: 64px; - height: 64px; - margin: 5px 5px 5px 0px; - background-repeat: no-repeat; - background-size: 64px 64px; +.oc-dialog .fileexists .original { + float: left; + width: 235px; +} +.oc-dialog .fileexists .conflict-wrapper { + overflow-y:scroll; + max-height: 225px; +} +.oc-dialog .fileexists .conflict-wrapper input[type='checkbox'] { float: left; - clear: both; } .oc-dialog .fileexists .toggle { @@ -234,9 +260,6 @@ table.dragshadow td.size { vertical-align: bottom; } -.oc-dialog .fileexists h3 { - font-weight: bold; -} .oc-dialog .oc-dialog-buttonrow { diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js index c620942170c..ec8c97ff457 100644 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -1,5 +1,44 @@ /** * + * and yet another idea how to handle file uploads: + * let the jquery fileupload thing handle as much as possible + * + * use singlefileupload + * on first add of every selection + * - check all files of originalFiles array with files in dir + * - on conflict show dialog + * - skip all -> remember as default action + * - replace all -> remember as default action + * - choose -> show choose dialog + * - mark files to keep + * - when only existing -> remember as single skip action + * - when only new -> remember as single replace action + * - when both -> remember as single autorename action + * - start uploading selection + * + * on send + * - if single action or default action + * - when skip -> abort upload + * ..- when replace -> add replace=true parameter + * ..- when rename -> add newName=filename parameter + * ..- when autorename -> add autorename=true parameter + * + * on fail + * - if server sent existserror + * - show dialog + * - on skip single -> abort single upload + * - on skip always -> remember as default action + * - on replace single -> replace single upload + * - on replace always -> remember as default action + * - on rename single -> rename single upload, propose autorename - when changed disable remember always checkbox + * - on rename always -> remember autorename as default action + * - resubmit data + * + * on uplad done + * - if last upload -> unset default action + * + * ------------------------------------------------------------- + * * use put t ocacnel upload before it starts? use chunked uploads? * * 1. tracking which file to upload next -> upload queue with data elements added whenever add is called @@ -202,11 +241,11 @@ OC.Upload = { data.submit(); }, logStatus:function(caption, e, data) { - console.log(caption+' ' +OC.Upload.loadedBytes()+' / '+OC.Upload.totalBytes()); - if (data) { - console.log(data); - } - console.log(e); + console.log(caption); + console.log(data); + }, + checkExistingFiles: function (selection, callbacks){ + callbacks.onNoConflicts(selection); } }; @@ -214,44 +253,110 @@ $(document).ready(function() { var file_upload_param = { dropZone: $('#content'), // restrict dropZone to content div + autoUpload: false, + sequentialUploads: true, //singleFileUploads is on by default, so the data.files array will always have length 1 + /** + * on first add of every selection + * - check all files of originalFiles array with files in dir + * - on conflict show dialog + * - skip all -> remember as single skip action for all conflicting files + * - replace all -> remember as single replace action for all conflicting files + * - choose -> show choose dialog + * - mark files to keep + * - when only existing -> remember as single skip action + * - when only new -> remember as single replace action + * - when both -> remember as single autorename action + * - start uploading selection + * @param {type} e + * @param {type} data + * @returns {Boolean} + */ add: function(e, data) { OC.Upload.logStatus('add', e, data); var that = $(this); - // lookup selection for dir - var selection = OC.Upload.getSelection(data.originalFiles); + // we need to collect all data upload objects before starting the upload so we can check their existence + // and set individual conflict actions. unfortunately there is only one variable that we can use to identify + // the selection a data upload is part of, so we have to collect them in data.originalFiles + // turning singleFileUploads off is not an option because we want to gracefully handle server errors like + // already exists - if (!selection.dir) { - selection.dir = $('#dir').val(); + // create a container where we can store the data objects + if ( ! data.originalFiles.selection ) { + // initialize selection and remember number of files to upload + data.originalFiles.selection = { + uploads: [], + filesToUpload: data.originalFiles.length, + totalBytes: 0 + }; } + var selection = data.originalFiles.selection; - if ( ! selection.checked ) { + // add uploads + if ( selection.uploads.length < selection.filesToUpload ){ + // remember upload + selection.uploads.push(data); + } + + //examine file + var file = data.files[0]; + + if (file.type === '' && file.size === 4096) { + data.textStatus = 'dirorzero'; + data.errorThrown = t('files', 'Unable to upload {filename} as it is a directory or has 0 bytes', + {filename: file.name} + ); + } + + // add size + selection.totalBytes += file.size; + + //check max upload size + if (selection.totalBytes > $('#max_upload').val()) { + data.textStatus = 'notenoughspace'; + data.errorThrown = t('files', 'Not enough space available'); + } + + // end upload for whole selection on error + if (data.errorThrown) { + // trigger fileupload fail + var fu = that.data('blueimp-fileupload') || that.data('fileupload'); + fu._trigger('fail', e, data); + return false; //don't upload anything + } + + // check existing files whan all is collected + if ( selection.uploads.length >= selection.filesToUpload ) { - selection.totalBytes = 0; - $.each(data.originalFiles, function(i, file) { - selection.totalBytes += file.size; + //remove our selection hack: + delete data.originalFiles.selection; - if (file.type === '' && file.size === 4096) { - data.textStatus = 'dirorzero'; - data.errorThrown = t('files', 'Unable to upload {filename} as it is a directory or has 0 bytes', - {filename: file.name} - ); - return false; + var callbacks = { + + onNoConflicts: function (selection) { + $.each(selection.uploads, function(i, upload) { + upload.submit(); + }); + }, + onSkipConflicts: function (selection) { + //TODO mark conflicting files as toskip + }, + onReplaceConflicts: function (selection) { + //TODO mark conflicting files as toreplace + }, + onChooseConflicts: function (selection) { + //TODO mark conflicting files as chosen + }, + onCancel: function (selection) { + $.each(selection.uploads, function(i, upload) { + upload.abort(); + }); } - }); + }; - if (selection.totalBytes > $('#max_upload').val()) { - data.textStatus = 'notenoughspace'; - data.errorThrown = t('files', 'Not enough space available'); - } - if (data.errorThrown) { - //don't upload anything - var fu = that.data('blueimp-fileupload') || that.data('fileupload'); - fu._trigger('fail', e, data); - return false; - } + OC.Upload.checkExistingFiles(selection, callbacks); //TODO refactor away: //show cancel button @@ -259,15 +364,8 @@ $(document).ready(function() { $('#uploadprogresswrapper input.stop').show(); } } + - //all subsequent add calls for this selection can be ignored - //allow navigating to the selection from a context - //context.selection = data.originalFiles.selection; - - //allow navigating to contexts / files of a selection - selection.files[data.files[0].name] = data; - - OC.Upload.queueUpload(data); //TODO check filename already exists /* @@ -283,7 +381,7 @@ $(document).ready(function() { } */ - return true; + return true; // continue adding files }, /** * called after the first add, does NOT have the data param @@ -314,8 +412,8 @@ $(document).ready(function() { $('#notification').fadeOut(); }, 5000); } - var selection = OC.Upload.getSelection(data.originalFiles); - OC.Upload.deleteSelectionUpload(selection, data.files[0].name); + //var selection = OC.Upload.getSelection(data.originalFiles); + //OC.Upload.deleteSelectionUpload(selection, data.files[0].name); //if user pressed cancel hide upload progress bar and cancel button if (data.errorThrown === 'abort') { @@ -339,8 +437,8 @@ $(document).ready(function() { if($('html.lte9').length > 0) { return; } - //var progress = (data.loaded/data.total)*100; - var progress = OC.Upload.progressBytes(); + var progress = (data.loaded/data.total)*100; + //var progress = OC.Upload.progressBytes(); $('#uploadprogressbar').progressbar('value', progress); }, /** @@ -359,15 +457,15 @@ $(document).ready(function() { response = data.result[0].body.innerText; } var result=$.parseJSON(response); - var selection = OC.Upload.getSelection(data.originalFiles); + //var selection = OC.Upload.getSelection(data.originalFiles); if(typeof result[0] !== 'undefined' && result[0].status === 'success' ) { - if (selection) { - selection.loadedBytes+=data.loaded; - } - OC.Upload.nextUpload(); + //if (selection) { + // selection.loadedBytes+=data.loaded; + //} + //OC.Upload.nextUpload(); } else { if (result[0].status === 'existserror') { //show "file already exists" dialog @@ -385,10 +483,10 @@ $(document).ready(function() { } //if user pressed cancel hide upload chrome - if (! OC.Upload.isProcessing()) { - $('#uploadprogresswrapper input.stop').fadeOut(); - $('#uploadprogressbar').fadeOut(); - } + //if (! OC.Upload.isProcessing()) { + // $('#uploadprogresswrapper input.stop').fadeOut(); + // $('#uploadprogressbar').fadeOut(); + //} }, /** @@ -398,27 +496,27 @@ $(document).ready(function() { */ stop: function(e, data) { OC.Upload.logStatus('stop', e, data); - if(OC.Upload.progressBytes()>=100) { //only hide controls when all selections have ended uploading + //if(OC.Upload.progressBytes()>=100) { //only hide controls when all selections have ended uploading - OC.Upload.cancelUploads(); //cleanup + //OC.Upload.cancelUploads(); //cleanup - if(data.dataType !== 'iframe') { - $('#uploadprogresswrapper input.stop').hide(); - } + // if(data.dataType !== 'iframe') { + // $('#uploadprogresswrapper input.stop').hide(); + // } //IE < 10 does not fire the necessary events for the progress bar. if($('html.lte9').length > 0) { return; } - $('#uploadprogressbar').progressbar('value', 100); - $('#uploadprogressbar').fadeOut(); - } + // $('#uploadprogressbar').progressbar('value', 100); + // $('#uploadprogressbar').fadeOut(); + //} //if user pressed cancel hide upload chrome - if (! OC.Upload.isProcessing()) { - $('#uploadprogresswrapper input.stop').fadeOut(); - $('#uploadprogressbar').fadeOut(); - } + //if (! OC.Upload.isProcessing()) { + // $('#uploadprogresswrapper input.stop').fadeOut(); + // $('#uploadprogressbar').fadeOut(); + //} } }; diff --git a/core/js/oc-dialogs.js b/core/js/oc-dialogs.js index ea03ef21455..a101cce9d1f 100644 --- a/core/js/oc-dialogs.js +++ b/core/js/oc-dialogs.js @@ -200,148 +200,221 @@ var OCdialogs = { alert(t('core', 'Error loading message template')); }); }, + _fileexistsshown: false, /** * Displays file exists dialog - * @param {object} original a file with name, size and mtime - * @param {object} replacement a file with name, size and mtime - * @param {object} controller a controller with onCancel, onSkip, onReplace and onRename methods + * @param {object} data upload object + * @param {object} original file with name, size and mtime + * @param {object} replacement file with name, size and mtime + * @param {object} controller with onCancel, onSkip, onReplace and onRename methods */ fileexists:function(data, original, replacement, controller) { + var self = this; var selection = controller.getSelection(data.originalFiles); if (selection.defaultAction) { controller[selection.defaultAction](data); } else { - $.when(this._getFileExistsTemplate()).then(function($tmpl) { - var dialog_name = 'oc-dialog-fileexists-' + OCdialogs.dialogs_counter + '-content'; - var dialog_id = '#' + dialog_name; - var title = t('files','Replace »{filename}«?',{filename: original.name}); - var original_size= t('files','Size: {size}',{size: original.size}); - var original_mtime = t('files','Last changed: {mtime}',{mtime: original.mtime}); - var replacement_size= t('files','Size: {size}',{size: replacement.size}); - var replacement_mtime = t('files','Last changed: {mtime}',{mtime: replacement.mtime}); - var $dlg = $tmpl.octemplate({ - dialog_name: dialog_name, - title: title, - type: 'fileexists', - - why: t('files','Another file with the same name already exists in "{dir}".',{dir:'somedir'}), - what: t('files','Replacing it will overwrite it\'s contents.'), - original_heading: t('files','Original file'), - original_size: original_size, - original_mtime: original_mtime, - - replacement_heading: t('files','Replace with'), - replacement_size: replacement_size, - replacement_mtime: replacement_mtime, - - new_name_label: t('files','Choose a new name for the target.'), - all_files_label: t('files','Use this action for all files.') - }); - $('body').append($dlg); - + var dialog_name = 'oc-dialog-fileexists-content'; + var dialog_id = '#' + dialog_name; + if (this._fileexistsshown) { + // add row + var conflict = $(dialog_id+ ' .conflict').last().clone(); + conflict.find('.name').text(original.name); + conflict.find('.original .size').text(humanFileSize(original.size)); + conflict.find('.original .mtime').text(formatDate(original.mtime*1000)); + conflict.find('.replacement .size').text(humanFileSize(replacement.size)); + conflict.find('.replacement .mtime').text(formatDate(replacement.lastModifiedDate)); getMimeIcon(original.type,function(path){ - $(dialog_id + ' .original .icon').css('background-image','url('+path+')'); + conflict.find('.original .icon').css('background-image','url('+path+')'); }); getMimeIcon(replacement.type,function(path){ - $(dialog_id + ' .replacement .icon').css('background-image','url('+path+')'); + conflict.find('.replacement .icon').css('background-image','url('+path+')'); }); - $(dialog_id + ' #newname').val(original.name); + $(dialog_id+' .conflict').last().after(conflict); + $(dialog_id).parent().children('.oc-dialog-title').text(t('files','{count} file conflicts',{count:$(dialog_id+ ' .conflict').length})); + + //set more recent mtime bold + if (replacement.lastModifiedDate.getTime() > original.mtime*1000) { + conflict.find('.replacement .mtime').css('font-weight', 'bold'); + } else if (replacement.lastModifiedDate.getTime() < original.mtime*1000) { + conflict.find('.original .mtime').css('font-weight', 'bold'); + } else { + //TODO add to same mtime colletion? + } + + // set bigger size bold + if (replacement.size > original.size) { + conflict.find('.replacement .size').css('font-weight','bold'); + } else if (replacement.size < original.size) { + conflict.find('.original .size').css('font-weight','bold'); + } else { + //TODO add to same size colletion? + } + + //add checkbox toggling actions + conflict.find('.replacement,.original').on('click', function(){ + var checkbox = $(this).find('input[type="checkbox"]'); + checkbox.prop('checkbox', !checkbox.prop('checkbox')); + }).find('input[type="checkbox"]').prop('checkbox',false); + + //TODO show skip action for files with same size and mtime + + $(window).trigger('resize'); + } else { + //create dialog + this._fileexistsshown = true; + $.when(this._getFileExistsTemplate()).then(function($tmpl) { + var title = t('files','One file conflict'); + var original_size = humanFileSize(original.size); + var original_mtime = formatDate(original.mtime*1000); + var replacement_size= humanFileSize(replacement.size); + var replacement_mtime = formatDate(replacement.lastModifiedDate); + var $dlg = $tmpl.octemplate({ + dialog_name: dialog_name, + title: title, + type: 'fileexists', + why: t('files','Which files do you want to keep?'), + what: t('files','If you select both versions, the copied file will have a number added to its name.'), + filename: original.name, + + original_size: original_size, + original_mtime: original_mtime, - $(dialog_id + ' #newname').on('keyup', function(e){ - if ($(dialog_id + ' #newname').val() === original.name) { - $(dialog_id + ' + div .rename').removeClass('primary').hide(); - $(dialog_id + ' + div .replace').addClass('primary').show(); - } else { - $(dialog_id + ' + div .rename').addClass('primary').show(); - $(dialog_id + ' + div .replace').removeClass('primary').hide(); - } - }); + replacement_size: replacement_size, + replacement_mtime: replacement_mtime + }); + $('body').append($dlg); - buttonlist = [{ - text: t('core', 'Cancel'), - classes: 'cancel', - click: function(){ - if ( typeof controller.onCancel !== 'undefined') { - controller.onCancel(data); - } - $(dialog_id).ocdialog('close'); - } - }, - { - text: t('core', 'Skip'), - classes: 'skip', - click: function(){ - if ( typeof controller.onSkip !== 'undefined') { - if($(dialog_id + ' #allfiles').prop('checked')){ - selection.defaultAction = 'onSkip'; - /*selection.defaultAction = function(){ - controller.onSkip(data); - };*/ - } - controller.onSkip(data); - } - // trigger fileupload done with status skip - //data.result[0].status = 'skip'; - //fileupload._trigger('done', data.e, data); - $(dialog_id).ocdialog('close'); + getMimeIcon(original.type,function(path){ + $(dialog_id + ' .original .icon').css('background-image','url('+path+')'); + }); + getMimeIcon(replacement.type,function(path){ + $(dialog_id + ' .replacement .icon').css('background-image','url('+path+')'); + }); + $(dialog_id + ' #newname').val(original.name); + + $(dialog_id + ' #newname').on('keyup', function(e){ + if ($(dialog_id + ' #newname').val() === original.name) { + $(dialog_id + ' + div .rename').removeClass('primary').hide(); + $(dialog_id + ' + div .replace').addClass('primary').show(); + } else { + $(dialog_id + ' + div .rename').addClass('primary').show(); + $(dialog_id + ' + div .replace').removeClass('primary').hide(); } - }, - { - text: t('core', 'Replace'), - classes: 'replace', - click: function(){ - if ( typeof controller.onReplace !== 'undefined') { - if($(dialog_id + ' #allfiles').prop('checked')){ - selection.defaultAction = 'onReplace'; - /*selection.defaultAction = function(){ - controller.onReplace(data); - };*/ + }); + + buttonlist = [{ + text: t('core', 'Cancel'), + classes: 'cancel', + click: function(){ + self._fileexistsshown = false; + if ( typeof controller.onCancel !== 'undefined') { + controller.onCancel(data); } - controller.onReplace(data); + $(dialog_id).ocdialog('close'); } - $(dialog_id).ocdialog('close'); }, - defaultButton: true - }, - { - text: t('core', 'Rename'), - classes: 'rename', - click: function(){ - if ( typeof controller.onRename !== 'undefined') { - //TODO use autorename when repeat is checked - controller.onRename(data, $(dialog_id + ' #newname').val()); + { + text: t('core', 'Continue'), + classes: 'continue', + click: function(){ + self._fileexistsshown = false; + if ( typeof controller.onRename !== 'undefined') { + //TODO use autorename when repeat is checked + controller.onRename(data, $(dialog_id + ' #newname').val()); + } + $(dialog_id).ocdialog('close'); } - $(dialog_id).ocdialog('close'); + }]; + + $(dialog_id).ocdialog({ + width: 500, + closeOnEscape: true, + modal: true, + buttons: buttonlist, + closeButton: null + }); + + $(dialog_id + ' + div .rename').hide(); + $(dialog_id + ' #newname').hide(); + + $(dialog_id + ' #newnamecb').on('change', function(){ + if ($(dialog_id + ' #newnamecb').prop('checked')) { + $(dialog_id + ' #newname').fadeIn(); + } else { + $(dialog_id + ' #newname').fadeOut(); + $(dialog_id + ' #newname').val(original.name); } - }]; + }); + $(dialog_id).css('height','auto'); - $(dialog_id).ocdialog({ - width: 500, - closeOnEscape: true, - modal: true, - buttons: buttonlist, - closeButton: null - }); - OCdialogs.dialogs_counter++; + var conflict = $(dialog_id + ' .conflict').last(); + //set more recent mtime bold + if (replacement.lastModifiedDate.getTime() > original.mtime*1000) { + conflict.find('.replacement .mtime').css('font-weight','bold'); + } else if (replacement.lastModifiedDate.getTime() < original.mtime*1000) { + conflict.find('.original .mtime').css('font-weight','bold'); + } else { + //TODO add to same mtime colletion? + } - $(dialog_id + ' + div .rename').hide(); - $(dialog_id + ' #newname').hide(); - - $(dialog_id + ' #newnamecb').on('change', function(){ - if ($(dialog_id + ' #newnamecb').prop('checked')) { - $(dialog_id + ' #newname').fadeIn(); + // set bigger size bold + if (replacement.size > original.size) { + conflict.find('.replacement .size').css('font-weight','bold'); + } else if (replacement.size < original.size) { + conflict.find('.original .size').css('font-weight','bold'); } else { - $(dialog_id + ' #newname').fadeOut(); - $(dialog_id + ' #newname').val(original.name); + //TODO add to same size colletion? } - }); - - }) - .fail(function() { - alert(t('core', 'Error loading file exists template')); - }); + //add checkbox toggling actions + //add checkbox toggling actions + $(dialog_id).find('.allnewfiles').on('click', function(){ + var checkboxes = $(dialog_id).find('.replacement input[type="checkbox"]'); + checkboxes.prop('checked', $(this).prop('checked')); + }); + $(dialog_id).find('.allexistingfiles').on('click', function(){ + var checkboxes = $(dialog_id).find('.original input[type="checkbox"]'); + checkboxes.prop('checked', $(this).prop('checked')); + }); + conflict.find('.replacement,.original').on('click', function(){ + var checkbox = $(this).find('input[type="checkbox"]'); + checkbox.prop('checked', !checkbox.prop('checked')); + }); + + //update counters + $(dialog_id).on('click', '.replacement,.allnewfiles', function(){ + var count = $(dialog_id).find('.replacement input[type="checkbox"]:checked').length; + if (count === $(dialog_id+ ' .conflict').length) { + $(dialog_id).find('.allnewfiles').prop('checked', true); + $(dialog_id).find('.allnewfiles + .count').text(t('files','(all selected)')); + } else if (count > 0) { + $(dialog_id).find('.allnewfiles').prop('checked', false); + $(dialog_id).find('.allnewfiles + .count').text(t('files','({count} selected)',{count:count})); + } else { + $(dialog_id).find('.allnewfiles').prop('checked', false); + $(dialog_id).find('.allnewfiles + .count').text(''); + } + }); + $(dialog_id).on('click', '.original,.allexistingfiles', function(){ + var count = $(dialog_id).find('.original input[type="checkbox"]:checked').length; + if (count === $(dialog_id+ ' .conflict').length) { + $(dialog_id).find('.allexistingfiles').prop('checked', true); + $(dialog_id).find('.allexistingfiles + .count').text(t('files','(all selected)')); + } else if (count > 0) { + $(dialog_id).find('.allexistingfiles').prop('checked', false); + $(dialog_id).find('.allexistingfiles + .count').text(t('files','({count} selected)',{count:count})); + } else { + $(dialog_id).find('.allexistingfiles').prop('checked', false); + $(dialog_id).find('.allexistingfiles + .count').text(''); + } + }); + }) + .fail(function() { + alert(t('core', 'Error loading file exists template')); + }); + } } }, _getFilePickerTemplate: function() { |