www/filemanager/upload/drag_drop_upload.js

Code
Comments
Other
Rev Date Author Line
7987 30 Jun 21 nicklas 1 /* $Id $
7987 30 Jun 21 nicklas 2   ------------------------------------------------------------------
7987 30 Jun 21 nicklas 3   Copyright (C) 2021 Nicklas Nordborg
7987 30 Jun 21 nicklas 4
7987 30 Jun 21 nicklas 5   This file is part of BASE - BioArray Software Environment.
7987 30 Jun 21 nicklas 6   Available at http://base.thep.lu.se/
7987 30 Jun 21 nicklas 7
7987 30 Jun 21 nicklas 8   BASE is free software; you can redistribute it and/or
7987 30 Jun 21 nicklas 9   modify it under the terms of the GNU General Public License
7987 30 Jun 21 nicklas 10   as published by the Free Software Foundation; either version 3
7987 30 Jun 21 nicklas 11   of the License, or (at your option) any later version.
7987 30 Jun 21 nicklas 12
7987 30 Jun 21 nicklas 13   BASE is distributed in the hope that it will be useful,
7987 30 Jun 21 nicklas 14   but WITHOUT ANY WARRANTY; without even the implied warranty of
7987 30 Jun 21 nicklas 15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
7987 30 Jun 21 nicklas 16   GNU General Public License for more details.
7987 30 Jun 21 nicklas 17
7987 30 Jun 21 nicklas 18   You should have received a copy of the GNU General Public License
7987 30 Jun 21 nicklas 19   along with BASE. If not, see <http://www.gnu.org/licenses/>.
7987 30 Jun 21 nicklas 20   ------------------------------------------------------------------
7987 30 Jun 21 nicklas 21
7987 30 Jun 21 nicklas 22   @author Nicklas
7987 30 Jun 21 nicklas 23 */
7987 30 Jun 21 nicklas 24 'use strict';
7987 30 Jun 21 nicklas 25
7987 30 Jun 21 nicklas 26 var Upload = function()
7987 30 Jun 21 nicklas 27 {
7987 30 Jun 21 nicklas 28   var upload = {};
8013 13 Aug 21 nicklas 29   var zipFormats = [];
7987 30 Jun 21 nicklas 30   
7988 30 Jun 21 nicklas 31   var filesAndFolders;
7988 30 Jun 21 nicklas 32   var currentFolder;
7988 30 Jun 21 nicklas 33   
7988 30 Jun 21 nicklas 34   var files = [];
7987 30 Jun 21 nicklas 35   var uploadRequest;
7991 01 Jul 21 nicklas 36   var uploadAborted = false;
7987 30 Jun 21 nicklas 37   
7987 30 Jun 21 nicklas 38   var totalFiles = 0;
7987 30 Jun 21 nicklas 39   var currentFile = 0;
7990 01 Jul 21 nicklas 40   var uploadedFiles = 0;
7990 01 Jul 21 nicklas 41   var skippedFiles = 0;
7987 30 Jun 21 nicklas 42   
7991 01 Jul 21 nicklas 43   var uploadStartTime;
7987 30 Jun 21 nicklas 44   var totalBytesToUpload = 0;
7987 30 Jun 21 nicklas 45   var bytesAlreadyUploaded = 0;
7990 01 Jul 21 nicklas 46   var skippedBytes = 0;
7987 30 Jun 21 nicklas 47   
7987 30 Jun 21 nicklas 48   /**
7987 30 Jun 21 nicklas 49     Initialize the page.
7987 30 Jun 21 nicklas 50   */
7987 30 Jun 21 nicklas 51   upload.initPage = function()
7987 30 Jun 21 nicklas 52   {
8013 13 Aug 21 nicklas 53     zipFormats = Data.json('page-data', 'zip-formats');
8013 13 Aug 21 nicklas 54
7990 01 Jul 21 nicklas 55     Buttons.addClickHandler('btnUpload', upload.beginFileUpload);
7990 01 Jul 21 nicklas 56     Buttons.addClickHandler('close', App.closeWindow);
7987 30 Jun 21 nicklas 57     Buttons.addClickHandler('btnAbort', upload.abortUpload);
7987 30 Jun 21 nicklas 58     Buttons.addClickHandler('failClose', App.closeWindow);
7987 30 Jun 21 nicklas 59
7988 30 Jun 21 nicklas 60     filesAndFolders = window.opener.FileManager.getFilesToUpload();
7988 30 Jun 21 nicklas 61     upload.processFilesAndFolders();
7988 30 Jun 21 nicklas 62   }
7988 30 Jun 21 nicklas 63   
8013 13 Aug 21 nicklas 64   /**
8013 13 Aug 21 nicklas 65     Get the ID of the best matching compressed format
8013 13 Aug 21 nicklas 66   */
8013 13 Aug 21 nicklas 67   upload.getCompressedFormat = function(filename)
8013 13 Aug 21 nicklas 68   {
8013 13 Aug 21 nicklas 69     var longestMatch = 0;
8013 13 Aug 21 nicklas 70     var bestFormat = null;
8013 13 Aug 21 nicklas 71     
8013 13 Aug 21 nicklas 72     for (var formatNo = 0; formatNo < zipFormats.length; formatNo++)
8013 13 Aug 21 nicklas 73     {
8013 13 Aug 21 nicklas 74       var zf = zipFormats[formatNo];
8013 13 Aug 21 nicklas 75       for (var extNo = 0; extNo < zf.extensions.length; extNo++)
8013 13 Aug 21 nicklas 76       {
8013 13 Aug 21 nicklas 77         var ext = '.' + zf.extensions[extNo];
8013 13 Aug 21 nicklas 78         var index = filename.lastIndexOf(ext);
8013 13 Aug 21 nicklas 79         if (index > 0 && (index + ext.length == filename.length))
8013 13 Aug 21 nicklas 80         {
8013 13 Aug 21 nicklas 81           if (ext.length > longestMatch)
8013 13 Aug 21 nicklas 82           {
8013 13 Aug 21 nicklas 83             longestMatch = ext.length;
8013 13 Aug 21 nicklas 84             bestFormat = zf;
8013 13 Aug 21 nicklas 85           }
8013 13 Aug 21 nicklas 86         }
8013 13 Aug 21 nicklas 87       }
8013 13 Aug 21 nicklas 88     }
8013 13 Aug 21 nicklas 89     return bestFormat;
8013 13 Aug 21 nicklas 90   }
8013 13 Aug 21 nicklas 91   
7990 01 Jul 21 nicklas 92   var currentDirectoryReader = null;
7988 30 Jun 21 nicklas 93   /*
7988 30 Jun 21 nicklas 94     Process all selected items (files and folder) and
7988 30 Jun 21 nicklas 95     put them in the 'files[]' upload queue.
7988 30 Jun 21 nicklas 96   */
7988 30 Jun 21 nicklas 97   upload.processFilesAndFolders = function()
7988 30 Jun 21 nicklas 98   {
7988 30 Jun 21 nicklas 99     if (filesAndFolders.length == 0)
7987 30 Jun 21 nicklas 100     {
7988 30 Jun 21 nicklas 101       // Nothing more to process -- start upload
7990 01 Jul 21 nicklas 102       upload.summarizePreProcessing();
7988 30 Jun 21 nicklas 103       return;
7987 30 Jun 21 nicklas 104     }
7988 30 Jun 21 nicklas 105     
7988 30 Jun 21 nicklas 106     // Get and remove the first entry from the process queue
7988 30 Jun 21 nicklas 107     // The filesAndFolder should contain 'FileSystemFileEntry' 
7988 30 Jun 21 nicklas 108     // and 'FileSystemDirectoryEntry' object
7988 30 Jun 21 nicklas 109     var ff = filesAndFolders.splice(0, 1)[0];
7988 30 Jun 21 nicklas 110     currentFolder = ff.subfolder || '';
8013 13 Aug 21 nicklas 111     // Ignore files/directories inside subfolders starting with '.' unless
8013 13 Aug 21 nicklas 112     // the top folder that was selected is also hidden
8013 13 Aug 21 nicklas 113     var ignore = ff.name.charAt(0)=='.' && (currentFolder.length > 0 && currentFolder.charAt(0)!='.');
8013 13 Aug 21 nicklas 114     if (!ignore)
7988 30 Jun 21 nicklas 115     {
8013 13 Aug 21 nicklas 116       if (ff.isFile)
8013 13 Aug 21 nicklas 117       {
8013 13 Aug 21 nicklas 118         // Get the file item as a 'File' object (its an async operation)
8013 13 Aug 21 nicklas 119         ff.file(upload.gotFile);
8013 13 Aug 21 nicklas 120         return;
8013 13 Aug 21 nicklas 121       }
8013 13 Aug 21 nicklas 122       else if (ff.isDirectory)
8013 13 Aug 21 nicklas 123       {
8013 13 Aug 21 nicklas 124         // Save the currentFolder for later use in 'upload.gotFolder'
8013 13 Aug 21 nicklas 125         currentFolder += ff.name+'/';
8013 13 Aug 21 nicklas 126         // Read files and subfolders (its an async operation)
8013 13 Aug 21 nicklas 127         currentDirectoryReader = ff.createReader();
8013 13 Aug 21 nicklas 128         currentDirectoryReader.readEntries(upload.gotFolder);
8013 13 Aug 21 nicklas 129         return;
8013 13 Aug 21 nicklas 130       }
7988 30 Jun 21 nicklas 131     }
8013 13 Aug 21 nicklas 132     
8013 13 Aug 21 nicklas 133     // Process next entry
8013 13 Aug 21 nicklas 134     upload.processFilesAndFolders();
7987 30 Jun 21 nicklas 135   }
7987 30 Jun 21 nicklas 136   
7988 30 Jun 21 nicklas 137   // We have a File item that should be upload
7988 30 Jun 21 nicklas 138   // Store and continue processing
7988 30 Jun 21 nicklas 139   upload.gotFile = function(file)
7988 30 Jun 21 nicklas 140   {
7988 30 Jun 21 nicklas 141     file.subfolder = currentFolder;
7988 30 Jun 21 nicklas 142     files[files.length] = file;
7988 30 Jun 21 nicklas 143     upload.processFilesAndFolders();
7988 30 Jun 21 nicklas 144   }
7988 30 Jun 21 nicklas 145   
7988 30 Jun 21 nicklas 146   // We have a list of more 'FileSystemFileEntry'/'FileSystemDirectoryEntry'
7988 30 Jun 21 nicklas 147   // object. Add them to the processing queue and continue with the next element
7988 30 Jun 21 nicklas 148   upload.gotFolder = function(moreFilesAndFolders)
7988 30 Jun 21 nicklas 149   {
7990 01 Jul 21 nicklas 150     if (moreFilesAndFolders.length == 0) 
7990 01 Jul 21 nicklas 151     {
7990 01 Jul 21 nicklas 152       currentDirectoryReader = null;
7990 01 Jul 21 nicklas 153       upload.processFilesAndFolders();
7990 01 Jul 21 nicklas 154       return;
7990 01 Jul 21 nicklas 155     }
7988 30 Jun 21 nicklas 156     for (var i = 0; i < moreFilesAndFolders.length; i++)
7988 30 Jun 21 nicklas 157     {
7988 30 Jun 21 nicklas 158       var item = moreFilesAndFolders[i];
7988 30 Jun 21 nicklas 159       item.subfolder = currentFolder;
7988 30 Jun 21 nicklas 160       filesAndFolders[filesAndFolders.length] = item;
7988 30 Jun 21 nicklas 161     }
7990 01 Jul 21 nicklas 162     // We need to repeat this call until we get an empty result, since
7990 01 Jul 21 nicklas 163     // some browsers (eg. chrome/edge) return a subset for each call.
7990 01 Jul 21 nicklas 164     currentDirectoryReader.readEntries(upload.gotFolder);
7988 30 Jun 21 nicklas 165   }
7988 30 Jun 21 nicklas 166   
7990 01 Jul 21 nicklas 167   upload.summarizePreProcessing = function()
7988 30 Jun 21 nicklas 168   {
7988 30 Jun 21 nicklas 169     if (files.length > 0)
7988 30 Jun 21 nicklas 170     {
7990 01 Jul 21 nicklas 171       files.sort(upload.sortFilesByFolder);
8013 13 Aug 21 nicklas 172       var html = '<table class="filelist" style="width: 100%;">';
7990 01 Jul 21 nicklas 173       var lastSubfolder = '';
7990 01 Jul 21 nicklas 174       var pad = '<td colspan="2" class="name">';
7990 01 Jul 21 nicklas 175       var numFolders = 1;
8013 13 Aug 21 nicklas 176       var numCompressedFiles = 0;
7988 30 Jun 21 nicklas 177       for (var i = 0; i < files.length; i++)
7988 30 Jun 21 nicklas 178       {
7988 30 Jun 21 nicklas 179         var f = files[i];
7988 30 Jun 21 nicklas 180         totalBytesToUpload += f.size;
7988 30 Jun 21 nicklas 181         totalFiles++;
8013 13 Aug 21 nicklas 182         if (upload.getCompressedFormat(f.name)) numCompressedFiles++;
7990 01 Jul 21 nicklas 183         if (totalFiles <= 500)
7990 01 Jul 21 nicklas 184         {
7990 01 Jul 21 nicklas 185           if (f.subfolder != lastSubfolder)
7990 01 Jul 21 nicklas 186           {
7990 01 Jul 21 nicklas 187             html += '<tr class="folder"><td colspan="3">'+Strings.encodeTags(f.subfolder)+'</td></tr>';
7990 01 Jul 21 nicklas 188             lastSubfolder = f.subfolder;
7990 01 Jul 21 nicklas 189             pad = '<td class="pad"></td><td class="name">';
7990 01 Jul 21 nicklas 190             numFolders++;
7990 01 Jul 21 nicklas 191           }
7990 01 Jul 21 nicklas 192           html += '<tr class="file">'+pad+Strings.encodeTags(f.name)+'</td><td class="size">'+Numbers.formatBytes(f.size)+'</td></tr>';
7990 01 Jul 21 nicklas 193         }
7988 30 Jun 21 nicklas 194       }
7990 01 Jul 21 nicklas 195       if (totalFiles > 500)
7990 01 Jul 21 nicklas 196       {
7990 01 Jul 21 nicklas 197         html += '<tr><td colspan="3" class="morefiles">+'+(totalFiles-500)+' more files...</td></tr>';
7990 01 Jul 21 nicklas 198       }
8013 13 Aug 21 nicklas 199       if (numCompressedFiles > 0) Doc.show('unpackSection');
7988 30 Jun 21 nicklas 200       var numFilesMsg = totalFiles==1?'1 file' : totalFiles+' files';
7988 30 Jun 21 nicklas 201       document.title = 'Uploading '+numFilesMsg+' to '+Data.get('page-data', 'directory-path');
7990 01 Jul 21 nicklas 202       Doc.element('mainTitle').innerHTML = document.title;
7990 01 Jul 21 nicklas 203       Doc.element('progressTitle').innerHTML = document.title;
7988 30 Jun 21 nicklas 204       Doc.element('totalBytes').innerHTML = Numbers.formatBytes(totalBytesToUpload);
7990 01 Jul 21 nicklas 205       
7990 01 Jul 21 nicklas 206       Doc.element('allFiles').innerHTML = html;
7990 01 Jul 21 nicklas 207       Doc.removeClass('btnUpload', 'disabled');
7988 30 Jun 21 nicklas 208     }
7988 30 Jun 21 nicklas 209     else
7988 30 Jun 21 nicklas 210     {
7988 30 Jun 21 nicklas 211       upload.displayError({'message': 'There are no files to upload'});
7988 30 Jun 21 nicklas 212     }
7988 30 Jun 21 nicklas 213   }
7988 30 Jun 21 nicklas 214   
7990 01 Jul 21 nicklas 215   upload.sortFilesByFolder = function(f1, f2)
7990 01 Jul 21 nicklas 216   {
7990 01 Jul 21 nicklas 217     if (f1.subfolder == f2.subfolder) return f1.name < f2.name ? -1 : 1;
7990 01 Jul 21 nicklas 218     return f1.subfolder < f2.subfolder ? -1 : 1;
7990 01 Jul 21 nicklas 219   }
7990 01 Jul 21 nicklas 220   
7990 01 Jul 21 nicklas 221   // Start the file uploading
7990 01 Jul 21 nicklas 222   upload.beginFileUpload = function()
7990 01 Jul 21 nicklas 223   {
7990 01 Jul 21 nicklas 224     Doc.hide('preUploadForm');
7990 01 Jul 21 nicklas 225     Doc.show('progressForm');
7991 01 Jul 21 nicklas 226     uploadStartTime = new Date().getTime();
7990 01 Jul 21 nicklas 227     upload.uploadNextFile();
7990 01 Jul 21 nicklas 228     upload.sendProgressUpdateRequest();
7990 01 Jul 21 nicklas 229   }
7990 01 Jul 21 nicklas 230   
7990 01 Jul 21 nicklas 231   var file;
7987 30 Jun 21 nicklas 232   upload.uploadNextFile = function()
7987 30 Jun 21 nicklas 233   {
7991 01 Jul 21 nicklas 234     if (uploadAborted) return;    
7990 01 Jul 21 nicklas 235     if (files.length == 0)
7990 01 Jul 21 nicklas 236     {
7990 01 Jul 21 nicklas 237       var numFilesMsg = uploadedFiles==1?'1 file' : uploadedFiles+' files';
7990 01 Jul 21 nicklas 238       var msg = numFilesMsg+' upload sucessfully';
7990 01 Jul 21 nicklas 239       if (skippedFiles > 0)
7990 01 Jul 21 nicklas 240       {
7990 01 Jul 21 nicklas 241         numFilesMsg = skippedFiles==1?'1 file' : skippedFiles+' files';
7990 01 Jul 21 nicklas 242         msg += ' ('+numFilesMsg+' skipped)';
7990 01 Jul 21 nicklas 243       }
7990 01 Jul 21 nicklas 244       var url = '../../common/close_popup.jsp?refresh_opener=1&message='+encodeURIComponent(msg);
7990 01 Jul 21 nicklas 245       window.top.location = url;
7990 01 Jul 21 nicklas 246       return;
7990 01 Jul 21 nicklas 247     }
7990 01 Jul 21 nicklas 248     
7990 01 Jul 21 nicklas 249     file = files.splice(0, 1)[0]; // Get first file and remove it from array
7987 30 Jun 21 nicklas 250     currentFile++;
7990 01 Jul 21 nicklas 251
7992 01 Jul 21 nicklas 252     var timeInSeconds = Math.round((new Date().getTime()-uploadStartTime)/1000);
7992 01 Jul 21 nicklas 253     upload.displayProgress(bytesAlreadyUploaded, totalBytesToUpload, timeInSeconds);
7991 01 Jul 21 nicklas 254     Doc.element('fileCount').innerHTML = currentFile+' of '+totalFiles; 
7991 01 Jul 21 nicklas 255     Doc.element('fileName').innerHTML = Strings.encodeTags(file.name)+' ('+Numbers.formatBytes(file.size)+')';
7991 01 Jul 21 nicklas 256     Doc.element('path').innerHTML = Data.get('page-data', 'directory-path')+'/'+file.subfolder;
7991 01 Jul 21 nicklas 257
7990 01 Jul 21 nicklas 258     var frm = document.forms['upload'];
7990 01 Jul 21 nicklas 259     if (frm.overwrite.value == 'always')
7990 01 Jul 21 nicklas 260     {
7990 01 Jul 21 nicklas 261       upload.doUpload(file, true);
7990 01 Jul 21 nicklas 262     }
7990 01 Jul 21 nicklas 263     else
7990 01 Jul 21 nicklas 264     {
7990 01 Jul 21 nicklas 265       var path = Data.get('page-data', 'directory-path')+'/'+file.subfolder+file.name;
7990 01 Jul 21 nicklas 266       var url = 'ajax.jsp?ID='+App.getSessionId();
7990 01 Jul 21 nicklas 267       url += '&cmd=CheckExistingFile';
7990 01 Jul 21 nicklas 268       url += '&path='+encodeURIComponent(path);
7990 01 Jul 21 nicklas 269       
7990 01 Jul 21 nicklas 270       var request = Ajax.getXmlHttpRequest();
7990 01 Jul 21 nicklas 271       request.open("GET", url, true);
7990 01 Jul 21 nicklas 272       Ajax.setReadyStateHandler(request, upload.fileCheckCallback);
7990 01 Jul 21 nicklas 273       request.send(null);
7990 01 Jul 21 nicklas 274     }
7987 30 Jun 21 nicklas 275   }
7987 30 Jun 21 nicklas 276   
7990 01 Jul 21 nicklas 277   upload.fileCheckCallback = function(request)
7987 30 Jun 21 nicklas 278   {
7990 01 Jul 21 nicklas 279     var check = JSON.parse(request.responseText);
7990 01 Jul 21 nicklas 280     var frm = document.forms['upload'];
7990 01 Jul 21 nicklas 281     var overwrite = frm.overwrite.value;
7990 01 Jul 21 nicklas 282     
7990 01 Jul 21 nicklas 283     if (check.fileExists)
7990 01 Jul 21 nicklas 284     {
7990 01 Jul 21 nicklas 285       if (overwrite == 'skipOrReplaceSize')
7990 01 Jul 21 nicklas 286       {
7990 01 Jul 21 nicklas 287         overwrite = check.fileSize != file.size ? 'always' : 'never';
7990 01 Jul 21 nicklas 288       }
7990 01 Jul 21 nicklas 289       if (overwrite == 'never') 
7990 01 Jul 21 nicklas 290       {
7990 01 Jul 21 nicklas 291         skippedFiles++;
7990 01 Jul 21 nicklas 292         skippedBytes += file.size;
7991 01 Jul 21 nicklas 293         bytesAlreadyUploaded += file.size;
7990 01 Jul 21 nicklas 294         upload.uploadNextFile();
7990 01 Jul 21 nicklas 295         return;
7990 01 Jul 21 nicklas 296       }
7990 01 Jul 21 nicklas 297     }
7990 01 Jul 21 nicklas 298     upload.doUpload(file, overwrite == 'always');
7990 01 Jul 21 nicklas 299   }
7990 01 Jul 21 nicklas 300   
7990 01 Jul 21 nicklas 301   upload.doUpload = function(file, overwrite)
7990 01 Jul 21 nicklas 302   {
7991 01 Jul 21 nicklas 303     if (uploadAborted) return;    
7991 01 Jul 21 nicklas 304     
7988 30 Jun 21 nicklas 305     // File name
7990 01 Jul 21 nicklas 306     var frm = document.forms['upload'];
7988 30 Jun 21 nicklas 307   
7987 30 Jun 21 nicklas 308     var upl = new FormData();
7988 30 Jun 21 nicklas 309     upl.set('subfolder', file.subfolder);
7988 30 Jun 21 nicklas 310     upl.set('autoSelect', totalFiles == 1 ? 1 : 0); // No automatic selection if we upload more than one file
7990 01 Jul 21 nicklas 311     upl.set('replace_existing', overwrite);
8013 13 Aug 21 nicklas 312     if (frm.unpackCompressed.checked)
8013 13 Aug 21 nicklas 313     {
8013 13 Aug 21 nicklas 314       var zipFormat = upload.getCompressedFormat(file.name);
8013 13 Aug 21 nicklas 315       if (zipFormat)
8013 13 Aug 21 nicklas 316       {
8013 13 Aug 21 nicklas 317         upl.set('zip_format', zipFormat.id);
8013 13 Aug 21 nicklas 318         upl.set('zip_unpack', 1);
8013 13 Aug 21 nicklas 319         upl.set('zip_overwrite', overwrite);
8013 13 Aug 21 nicklas 320         upl.set('zip_keep', 0);
8013 13 Aug 21 nicklas 321       }
8013 13 Aug 21 nicklas 322     }
7990 01 Jul 21 nicklas 323     upl.set('description', frm.description.value);
7987 30 Jun 21 nicklas 324     upl.set('the_file', file);
7987 30 Jun 21 nicklas 325     
7987 30 Jun 21 nicklas 326     var url = 'Upload?ID='+App.getSessionId();
7987 30 Jun 21 nicklas 327     url += '&directory_id='+Data.get('page-data', 'directory-id');
7987 30 Jun 21 nicklas 328
7987 30 Jun 21 nicklas 329     uploadRequest = Ajax.getXmlHttpRequest();
7987 30 Jun 21 nicklas 330     Ajax.setReadyStateHandler(uploadRequest, upload.uploadComplete, upload.uploadComplete);
7987 30 Jun 21 nicklas 331     uploadRequest.open('POST', url, true);
7987 30 Jun 21 nicklas 332     uploadRequest.send(upl);
7987 30 Jun 21 nicklas 333   }
7987 30 Jun 21 nicklas 334
7987 30 Jun 21 nicklas 335
7987 30 Jun 21 nicklas 336   upload.uploadComplete = function(request)
7987 30 Jun 21 nicklas 337   {
7987 30 Jun 21 nicklas 338     // If we have called uploadRequest.abort()
7987 30 Jun 21 nicklas 339     // we do not need error handling here
7987 30 Jun 21 nicklas 340     if (request.status == 0) return;
7987 30 Jun 21 nicklas 341     var result = {};
7987 30 Jun 21 nicklas 342     try
7987 30 Jun 21 nicklas 343     {
7987 30 Jun 21 nicklas 344       var contentType = request.getResponseHeader('Content-Type');
7987 30 Jun 21 nicklas 345       if (request.status != 200 || contentType.indexOf('json') == -1)
7987 30 Jun 21 nicklas 346       {
7987 30 Jun 21 nicklas 347         throw new Error(request.responseText);
7987 30 Jun 21 nicklas 348       }
7987 30 Jun 21 nicklas 349       result = JSON.parse(request.responseText);      
7987 30 Jun 21 nicklas 350     }
7987 30 Jun 21 nicklas 351     catch (err)
7987 30 Jun 21 nicklas 352     {
7987 30 Jun 21 nicklas 353       result.status = 'error';
7987 30 Jun 21 nicklas 354       result.message = err;
7987 30 Jun 21 nicklas 355     }
7987 30 Jun 21 nicklas 356     if (result.status == 'ok')
7987 30 Jun 21 nicklas 357     {
7990 01 Jul 21 nicklas 358       bytesAlreadyUploaded += result.transferredBytes;
7990 01 Jul 21 nicklas 359       uploadedFiles++;
7990 01 Jul 21 nicklas 360       upload.uploadNextFile();
7987 30 Jun 21 nicklas 361     }
7987 30 Jun 21 nicklas 362     else
7987 30 Jun 21 nicklas 363     {
7987 30 Jun 21 nicklas 364       upload.displayError(result);
7987 30 Jun 21 nicklas 365     }
7987 30 Jun 21 nicklas 366   }
7987 30 Jun 21 nicklas 367
7987 30 Jun 21 nicklas 368   upload.sendProgressUpdateRequest = function()
7987 30 Jun 21 nicklas 369   {
7987 30 Jun 21 nicklas 370     var request = Ajax.getXmlHttpRequest();
7987 30 Jun 21 nicklas 371     var url = 'ajax.jsp?ID='+App.getSessionId();
7987 30 Jun 21 nicklas 372     url += '&cmd=GetProgress&'+Math.random();
7987 30 Jun 21 nicklas 373     request.open("GET", url, true);
7987 30 Jun 21 nicklas 374     Ajax.setReadyStateHandler(request, upload.progressUpdateCallback);
7987 30 Jun 21 nicklas 375     request.send(null);
7987 30 Jun 21 nicklas 376   }
7987 30 Jun 21 nicklas 377   
7987 30 Jun 21 nicklas 378   upload.progressUpdateCallback = function(request)
7987 30 Jun 21 nicklas 379   {
7987 30 Jun 21 nicklas 380     var progress = JSON.parse(request.responseText);
7987 30 Jun 21 nicklas 381     if (progress)
7987 30 Jun 21 nicklas 382     {
7987 30 Jun 21 nicklas 383       if (progress.status == 'ok')
7987 30 Jun 21 nicklas 384       {
7987 30 Jun 21 nicklas 385         if (progress.file)
7987 30 Jun 21 nicklas 386         {
7987 30 Jun 21 nicklas 387           var transferredBytes = bytesAlreadyUploaded + progress.transferredBytes;
7991 01 Jul 21 nicklas 388           var timeInSeconds = Math.round((new Date().getTime()-uploadStartTime)/1000);
7987 30 Jun 21 nicklas 389           var message = progress.message;
7992 01 Jul 21 nicklas 390           upload.displayProgress(transferredBytes, totalBytesToUpload, timeInSeconds, message);
7987 30 Jun 21 nicklas 391         }
7987 30 Jun 21 nicklas 392       }
7987 30 Jun 21 nicklas 393       else
7987 30 Jun 21 nicklas 394       {
7987 30 Jun 21 nicklas 395         upload.displayError(progress);
7991 01 Jul 21 nicklas 396         if (uploadRequest) uploadRequest.abort(); // Important!! Otherwise the browser may try to re-send the request
7987 30 Jun 21 nicklas 397         return;
7987 30 Jun 21 nicklas 398       }
7987 30 Jun 21 nicklas 399     }
7987 30 Jun 21 nicklas 400     setTimeout(upload.sendProgressUpdateRequest, 1500);
7987 30 Jun 21 nicklas 401   }
7987 30 Jun 21 nicklas 402
7992 01 Jul 21 nicklas 403   upload.displayProgress = function(transferredBytes, totalBytes, transferTime, message)
7987 30 Jun 21 nicklas 404   {
7987 30 Jun 21 nicklas 405     // Percent done
7987 30 Jun 21 nicklas 406     var percentDone = totalBytes == 0 ? 0 : Math.round(100 * transferredBytes / totalBytes);
7987 30 Jun 21 nicklas 407     Doc.element('percentText').innerHTML = percentDone+'%';
7987 30 Jun 21 nicklas 408     var doneElement = Doc.element('percentDone');
7987 30 Jun 21 nicklas 409     doneElement.style.width = percentDone+'%';
7987 30 Jun 21 nicklas 410     var remainElement = Doc.element('percentRemain');
7987 30 Jun 21 nicklas 411     remainElement.style.width = (100-percentDone)+'%';
7987 30 Jun 21 nicklas 412     if (percentDone == 100) Doc.hide('percentRemain');
7987 30 Jun 21 nicklas 413     
7987 30 Jun 21 nicklas 414     // Bytes
7987 30 Jun 21 nicklas 415     Doc.element('transferredBytes').innerHTML = Numbers.formatBytes(transferredBytes);
7990 01 Jul 21 nicklas 416     Doc.element('totalBytes').innerHTML = Numbers.formatBytes(totalBytes);
7990 01 Jul 21 nicklas 417     if (skippedBytes > 0)
7990 01 Jul 21 nicklas 418     {
7990 01 Jul 21 nicklas 419       var numFilesMsg = skippedFiles==1?'1 file' : skippedFiles+' files';
7990 01 Jul 21 nicklas 420       Doc.element('skippedBytes').innerHTML = ' (Skipped '+numFilesMsg+'; '+Numbers.formatBytes(skippedBytes)+')';
7990 01 Jul 21 nicklas 421     }
7987 30 Jun 21 nicklas 422
7987 30 Jun 21 nicklas 423     // Times and rate
7987 30 Jun 21 nicklas 424     Doc.element('transferTime').innerHTML = Numbers.formatSeconds(transferTime);
7987 30 Jun 21 nicklas 425     var transferRate = transferTime == 0 ? 0 : transferredBytes / transferTime;
7992 01 Jul 21 nicklas 426     var fileRate = transferTime == 0 ? 0 : currentFile / transferTime;
7987 30 Jun 21 nicklas 427     Doc.element('transferRate').innerHTML = '(' + Numbers.formatBytes(transferRate) + '/s)';
7992 01 Jul 21 nicklas 428     if (transferRate > 0 && fileRate > 0)
7987 30 Jun 21 nicklas 429     {
7992 01 Jul 21 nicklas 430       var remainTime = Math.max(Math.ceil((totalBytes-transferredBytes)/transferRate), Math.ceil((totalFiles-currentFile)/fileRate));
7992 01 Jul 21 nicklas 431       if (remainTime < 0) remainTime = 0;
7987 30 Jun 21 nicklas 432       Doc.element('remainTime').innerHTML = Numbers.formatSeconds(remainTime) + ' (estimated)';
7987 30 Jun 21 nicklas 433     }
7987 30 Jun 21 nicklas 434     
7987 30 Jun 21 nicklas 435     // Message
7987 30 Jun 21 nicklas 436     if (message)
7987 30 Jun 21 nicklas 437     {
7987 30 Jun 21 nicklas 438       Doc.element('message').innerHTML = message.replace(/(.*):(.*)/, '<th>$1</th><td>$2</td>');
7987 30 Jun 21 nicklas 439     }
7987 30 Jun 21 nicklas 440     else
7987 30 Jun 21 nicklas 441     {
7987 30 Jun 21 nicklas 442       Doc.element('message').innerHTML = '';
7987 30 Jun 21 nicklas 443     }
7987 30 Jun 21 nicklas 444   }
7987 30 Jun 21 nicklas 445
7987 30 Jun 21 nicklas 446   upload.displayError = function(result)
7987 30 Jun 21 nicklas 447   {
7987 30 Jun 21 nicklas 448     Doc.show('uploadFailed');
7987 30 Jun 21 nicklas 449     Doc.hide('progressForm');
7990 01 Jul 21 nicklas 450     Doc.hide('preUploadForm');
7987 30 Jun 21 nicklas 451     Doc.element('failTitle').innerHTML = result.title || 'File upload failed';
7987 30 Jun 21 nicklas 452     Doc.element('failMessage').innerHTML = result.message || result.stacktrace;
7987 30 Jun 21 nicklas 453     if (result.status == 'abort') setTimeout(App.closeWindow, 1500);
7987 30 Jun 21 nicklas 454   }
7987 30 Jun 21 nicklas 455
7987 30 Jun 21 nicklas 456   upload.abortUpload = function()
7987 30 Jun 21 nicklas 457   {
7987 30 Jun 21 nicklas 458     if (confirm('Are you sure you want to abort the upload? It cannot be resumed.'))
7987 30 Jun 21 nicklas 459     {
7987 30 Jun 21 nicklas 460       /*
7987 30 Jun 21 nicklas 461       Aborting is tricky. See tickets:
7987 30 Jun 21 nicklas 462       http://base.thep.lu.se/ticket/2018
7987 30 Jun 21 nicklas 463       http://base.thep.lu.se/ticket/2019
7987 30 Jun 21 nicklas 464       
7987 30 Jun 21 nicklas 465       Sending "Abort" command to the server AND 
7987 30 Jun 21 nicklas 466       uploadRequest.abort() should tell both ends.
7987 30 Jun 21 nicklas 467       The "abort" is catched by the progress updater that
7987 30 Jun 21 nicklas 468       also display the error message.
7987 30 Jun 21 nicklas 469       */
7991 01 Jul 21 nicklas 470       uploadAborted = true;
7991 01 Jul 21 nicklas 471       if (uploadRequest) uploadRequest.abort();
7991 01 Jul 21 nicklas 472       
7987 30 Jun 21 nicklas 473       var url = 'ajax.jsp?ID='+App.getSessionId();
7987 30 Jun 21 nicklas 474       url += '&cmd=Abort&'+Math.random();
7991 01 Jul 21 nicklas 475       var request = Ajax.getXmlHttpRequest();
7991 01 Jul 21 nicklas 476       Ajax.setReadyStateHandler(request, upload.abortProgressCallback);
7987 30 Jun 21 nicklas 477       request.open("GET", url, true);
7987 30 Jun 21 nicklas 478       request.send(null);
7991 01 Jul 21 nicklas 479     }
7991 01 Jul 21 nicklas 480   }
7987 30 Jun 21 nicklas 481
7991 01 Jul 21 nicklas 482   upload.abortProgressCallback = function(request)
7991 01 Jul 21 nicklas 483   {
7991 01 Jul 21 nicklas 484     var progress = JSON.parse(request.responseText);
7991 01 Jul 21 nicklas 485     if (!progress.aborted) 
7991 01 Jul 21 nicklas 486     {
7991 01 Jul 21 nicklas 487       // There was no active upload, so we simply abort...
7991 01 Jul 21 nicklas 488       upload.displayError({'status': 'abort', 'message': 'The upload was aborted'});
7987 30 Jun 21 nicklas 489     }
7987 30 Jun 21 nicklas 490   }
7987 30 Jun 21 nicklas 491
7987 30 Jun 21 nicklas 492   return upload;
7987 30 Jun 21 nicklas 493 }();
7987 30 Jun 21 nicklas 494
7987 30 Jun 21 nicklas 495 Doc.onLoad(Upload.initPage);