2014-01-30 09:41:04 +00:00
/ *
* Copyright ( c ) 2014
*
* This file is licensed under the Affero General Public License version 3
* or later .
*
* See the COPYING - README file .
*
* /
2013-08-14 15:49:45 +00:00
/ * *
2013-09-08 08:41:20 +00:00
* The file upload code uses several hooks to interact with blueimps jQuery file upload library :
* 1. the core upload handling hooks are added when initializing the plugin ,
* 2. if the browser supports progress events they are added in a separate set after the initialization
* 3. every app can add it ' s own triggers for fileupload
* - files adds d 'n' d handlers and also reacts to done events to add new rows to the filelist
* - TODO pictures upload button
* - TODO music upload button
2013-08-14 15:49:45 +00:00
* /
2014-05-09 12:06:59 +00:00
/* global Files, FileList, jQuery, oc_requesttoken, humanFileSize, getUniqueName */
2014-01-30 09:41:04 +00:00
2013-09-16 12:10:19 +00:00
/ * *
* Function that will allow us to know if Ajax uploads are supported
* @ link https : //github.com/New-Bamboo/example-ajax-upload/blob/master/public/index.html
* also see article @ link http : //blog.new-bamboo.co.uk/2012/01/10/ridiculously-simple-ajax-uploads-with-formdata
* /
2013-09-05 08:19:54 +00:00
function supportAjaxUploadWithProgress ( ) {
return supportFileAPI ( ) && supportAjaxUploadProgressEvents ( ) && supportFormData ( ) ;
2013-08-14 15:49:45 +00:00
2013-09-05 08:19:54 +00:00
// Is the File API supported?
function supportFileAPI ( ) {
var fi = document . createElement ( 'INPUT' ) ;
fi . type = 'file' ;
return 'files' in fi ;
2013-10-22 20:39:28 +00:00
}
2013-09-05 08:19:54 +00:00
// Are progress events supported?
function supportAjaxUploadProgressEvents ( ) {
var xhr = new XMLHttpRequest ( ) ;
return ! ! ( xhr && ( 'upload' in xhr ) && ( 'onprogress' in xhr . upload ) ) ;
2013-10-22 20:39:28 +00:00
}
2013-09-05 08:19:54 +00:00
// Is FormData supported?
function supportFormData ( ) {
return ! ! window . FormData ;
}
}
2013-08-16 09:40:55 +00:00
2013-09-08 08:41:20 +00:00
/ * *
* keeps track of uploads in progress and implements callbacks for the conflicts dialog
2013-09-19 09:11:22 +00:00
* @ type { OC . Upload }
2013-09-08 08:41:20 +00:00
* /
2013-08-16 09:40:55 +00:00
OC . Upload = {
2013-09-06 20:40:10 +00:00
_uploads : [ ] ,
2013-09-08 08:41:20 +00:00
/ * *
* deletes the jqHXR object from a data selection
2013-09-19 09:11:22 +00:00
* @ param { object } data
2013-09-08 08:41:20 +00:00
* /
2013-09-06 20:40:10 +00:00
deleteUpload : function ( data ) {
delete data . jqXHR ;
} ,
2013-09-08 08:41:20 +00:00
/ * *
* cancels all uploads
* /
2013-08-16 09:40:55 +00:00
cancelUploads : function ( ) {
2013-09-18 12:39:39 +00:00
this . log ( 'canceling uploads' ) ;
2014-05-09 12:06:59 +00:00
jQuery . each ( this . _uploads , function ( i , jqXHR ) {
2013-09-06 20:40:10 +00:00
jqXHR . abort ( ) ;
2013-08-16 09:40:55 +00:00
} ) ;
2013-09-06 20:40:10 +00:00
this . _uploads = [ ] ;
2013-06-26 20:51:38 +00:00
} ,
2013-10-22 16:11:03 +00:00
rememberUpload : function ( jqXHR ) {
2013-09-06 20:40:10 +00:00
if ( jqXHR ) {
this . _uploads . push ( jqXHR ) ;
2013-06-26 20:51:38 +00:00
}
2013-08-16 09:40:55 +00:00
} ,
2013-09-08 08:41:20 +00:00
/ * *
* Checks the currently known uploads .
* returns true if any hxr has the state 'pending'
2013-09-19 09:11:22 +00:00
* @ returns { boolean }
2013-09-08 08:41:20 +00:00
* /
2013-10-22 16:11:03 +00:00
isProcessing : function ( ) {
2013-09-06 20:40:10 +00:00
var count = 0 ;
2014-03-04 15:42:40 +00:00
2014-05-09 12:06:59 +00:00
jQuery . each ( this . _uploads , function ( i , data ) {
2013-09-06 20:40:10 +00:00
if ( data . state ( ) === 'pending' ) {
count ++ ;
}
2013-08-16 09:40:55 +00:00
} ) ;
2013-09-06 20:40:10 +00:00
return count > 0 ;
2013-06-26 20:51:38 +00:00
} ,
2013-09-08 08:41:20 +00:00
/ * *
* callback for the conflicts dialog
2013-09-19 09:11:22 +00:00
* @ param { object } data
2013-09-08 08:41:20 +00:00
* /
2013-09-05 15:46:19 +00:00
onCancel : function ( data ) {
2013-09-06 20:40:10 +00:00
this . cancelUploads ( ) ;
2013-08-12 10:33:22 +00:00
} ,
2013-09-08 08:41:20 +00:00
/ * *
* callback for the conflicts dialog
* calls onSkip , onReplace or onAutorename for each conflict
2013-09-19 09:11:22 +00:00
* @ param { object } conflicts - list of conflict elements
2013-09-08 08:41:20 +00:00
* /
2013-09-05 15:46:19 +00:00
onContinue : function ( conflicts ) {
var self = this ;
//iterate over all conflicts
jQuery . each ( conflicts , function ( i , conflict ) {
conflict = $ ( conflict ) ;
var keepOriginal = conflict . find ( '.original input[type="checkbox"]:checked' ) . length === 1 ;
var keepReplacement = conflict . find ( '.replacement input[type="checkbox"]:checked' ) . length === 1 ;
if ( keepOriginal && keepReplacement ) {
// when both selected -> autorename
self . onAutorename ( conflict . data ( 'data' ) ) ;
} else if ( keepReplacement ) {
// when only replacement selected -> overwrite
self . onReplace ( conflict . data ( 'data' ) ) ;
} else {
// when only original seleted -> skip
// when none selected -> skip
self . onSkip ( conflict . data ( 'data' ) ) ;
}
} ) ;
} ,
2013-09-08 08:41:20 +00:00
/ * *
* handle skipping an upload
2013-09-19 09:11:22 +00:00
* @ param { object } data
2013-09-08 08:41:20 +00:00
* /
2013-10-22 16:11:03 +00:00
onSkip : function ( data ) {
2013-09-18 12:39:39 +00:00
this . log ( 'skip' , null , data ) ;
2013-09-06 20:40:10 +00:00
this . deleteUpload ( data ) ;
2013-06-26 20:51:38 +00:00
} ,
2013-09-08 08:41:20 +00:00
/ * *
* handle replacing a file on the server with an uploaded file
2013-09-19 09:11:22 +00:00
* @ param { object } data
2013-09-08 08:41:20 +00:00
* /
2013-10-22 16:11:03 +00:00
onReplace : function ( data ) {
2013-09-18 12:39:39 +00:00
this . log ( 'replace' , null , data ) ;
2013-10-22 16:11:03 +00:00
if ( data . data ) {
2013-10-10 13:54:00 +00:00
data . data . append ( 'resolution' , 'replace' ) ;
} else {
2013-10-22 16:11:03 +00:00
data . formData . push ( { name : 'resolution' , value : 'replace' } ) ; //hack for ie8
2013-10-10 13:54:00 +00:00
}
2013-08-12 10:33:22 +00:00
data . submit ( ) ;
2013-06-26 20:51:38 +00:00
} ,
2013-09-08 08:41:20 +00:00
/ * *
* handle uploading a file and letting the server decide a new name
2013-09-19 09:11:22 +00:00
* @ param { object } data
2013-09-08 08:41:20 +00:00
* /
2013-10-22 16:11:03 +00:00
onAutorename : function ( data ) {
2013-09-18 12:39:39 +00:00
this . log ( 'autorename' , null , data ) ;
2013-09-06 21:44:40 +00:00
if ( data . data ) {
data . data . append ( 'resolution' , 'autorename' ) ;
} else {
2013-10-22 16:11:03 +00:00
data . formData . push ( { name : 'resolution' , value : 'autorename' } ) ; //hack for ie8
2013-09-06 21:44:40 +00:00
}
2013-08-12 10:33:22 +00:00
data . submit ( ) ;
2013-08-16 09:40:55 +00:00
} ,
2013-09-18 12:39:39 +00:00
_trace : false , //TODO implement log handler for JS per class?
log : function ( caption , e , data ) {
if ( this . _trace ) {
console . log ( caption ) ;
console . log ( data ) ;
}
2013-08-22 12:29:00 +00:00
} ,
2013-09-08 08:41:20 +00:00
/ * *
* TODO checks the list of existing files prior to uploading and shows a simple dialog to choose
2013-09-19 09:13:11 +00:00
* skip all , replace all or choose which files to keep
2013-09-19 09:11:22 +00:00
* @ param { array } selection of files to upload
* @ param { object } callbacks - object with several callback methods
* @ param { function } callbacks . onNoConflicts
* @ param { function } callbacks . onSkipConflicts
* @ param { function } callbacks . onReplaceConflicts
* @ param { function } callbacks . onChooseConflicts
* @ param { function } callbacks . onCancel
2013-09-08 08:41:20 +00:00
* /
2013-10-22 16:11:03 +00:00
checkExistingFiles : function ( selection , callbacks ) {
2013-09-08 08:41:20 +00:00
// TODO check filelist before uploading and show dialog on conflicts, use callbacks
2013-08-22 12:29:00 +00:00
callbacks . onNoConflicts ( selection ) ;
2014-03-06 12:49:57 +00:00
} ,
2014-03-04 15:42:40 +00:00
2014-05-23 17:02:50 +00:00
_hideProgressBar : function ( ) {
$ ( '#uploadprogresswrapper input.stop' ) . fadeOut ( ) ;
$ ( '#uploadprogressbar' ) . fadeOut ( function ( ) {
$ ( '#file_upload_start' ) . trigger ( new $ . Event ( 'resized' ) ) ;
} ) ;
} ,
_showProgressBar : function ( ) {
$ ( '#uploadprogressbar' ) . fadeIn ( ) ;
$ ( '#file_upload_start' ) . trigger ( new $ . Event ( 'resized' ) ) ;
} ,
2014-03-06 12:49:57 +00:00
init : function ( ) {
2013-10-28 19:22:06 +00:00
if ( $ ( '#file_upload_start' ) . exists ( ) ) {
2014-03-06 12:49:57 +00:00
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 { object } e
* @ param { object } data
* @ returns { boolean }
* /
add : function ( e , data ) {
OC . Upload . log ( 'add' , e , data ) ;
2014-05-09 12:06:59 +00:00
var that = $ ( this ) , freeSpace ;
2014-03-06 12:49:57 +00:00
2014-05-09 12:06:59 +00:00
// 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'
2014-03-06 12:49:57 +00:00
// 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 ;
2014-03-04 15:42:40 +00:00
2014-03-06 12:49:57 +00:00
// add uploads
if ( selection . uploads . length < selection . filesToUpload ) {
// remember upload
selection . uploads . push ( data ) ;
}
2014-03-04 15:42:40 +00:00
2014-03-06 12:49:57 +00:00
//examine file
var file = data . files [ 0 ] ;
try {
// FIXME: not so elegant... need to refactor that method to return a value
2014-04-08 15:17:48 +00:00
Files . isFileNameValid ( file . name ) ;
2014-03-06 12:49:57 +00:00
}
catch ( errorMessage ) {
data . textStatus = 'invalidcharacters' ;
data . errorThrown = errorMessage ;
}
2013-12-08 15:17:35 +00:00
2014-04-09 21:32:12 +00:00
// in case folder drag and drop is not supported file will point to a directory
2014-04-15 19:39:13 +00:00
// http://stackoverflow.com/a/20448357
2014-05-09 12:06:59 +00:00
if ( ! file . type && file . size % 4096 === 0 && file . size <= 102400 ) {
2014-04-09 21:32:12 +00:00
try {
2014-05-09 12:06:59 +00:00
var reader = new FileReader ( ) ;
reader . readAsBinaryString ( file ) ;
2014-04-09 21:32:12 +00:00
} catch ( NS _ERROR _FILE _ACCESS _DENIED ) {
//file is a directory
data . textStatus = 'dirorzero' ;
2014-05-09 12:06:59 +00:00
data . errorThrown = t ( 'files' ,
'Unable to upload {filename} as it is a directory or has 0 bytes' ,
2014-04-09 21:32:12 +00:00
{ filename : file . name }
) ;
}
2014-03-06 12:49:57 +00:00
}
2014-03-04 15:42:40 +00:00
2014-03-06 12:49:57 +00:00
// add size
selection . totalBytes += file . size ;
2013-08-22 12:29:00 +00:00
2014-03-06 12:49:57 +00:00
// check PHP upload limit
if ( selection . totalBytes > $ ( '#upload_limit' ) . val ( ) ) {
data . textStatus = 'sizeexceedlimit' ;
2014-05-09 12:06:59 +00:00
data . errorThrown = t ( 'files' ,
'Total file size {size1} exceeds upload limit {size2}' , {
2014-03-06 12:49:57 +00:00
'size1' : humanFileSize ( selection . totalBytes ) ,
'size2' : humanFileSize ( $ ( '#upload_limit' ) . val ( ) )
} ) ;
}
2014-03-04 15:42:40 +00:00
2014-03-06 12:49:57 +00:00
// check free space
2014-03-06 12:50:53 +00:00
freeSpace = $ ( '#free_space' ) . val ( ) ;
if ( freeSpace >= 0 && selection . totalBytes > freeSpace ) {
2014-03-06 12:49:57 +00:00
data . textStatus = 'notenoughspace' ;
2014-05-09 12:06:59 +00:00
data . errorThrown = t ( 'files' ,
'Not enough free space, you are uploading {size1} but only {size2} is left' , {
2014-03-06 12:49:57 +00:00
'size1' : humanFileSize ( selection . totalBytes ) ,
'size2' : humanFileSize ( $ ( '#free_space' ) . val ( ) )
} ) ;
}
2013-06-26 20:51:38 +00:00
2014-03-06 12:49:57 +00:00
// 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
}
2014-03-04 15:42:40 +00:00
2014-03-06 12:49:57 +00:00
// check existing files when all is collected
if ( selection . uploads . length >= selection . filesToUpload ) {
//remove our selection hack:
delete data . originalFiles . selection ;
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 ( ) ;
} ) ;
}
} ;
2013-06-26 20:51:38 +00:00
2014-03-06 12:49:57 +00:00
OC . Upload . checkExistingFiles ( selection , callbacks ) ;
2014-03-04 15:42:40 +00:00
2014-03-06 12:49:57 +00:00
}
2013-06-26 20:51:38 +00:00
2014-03-06 12:49:57 +00:00
return true ; // continue adding files
} ,
/ * *
* called after the first add , does NOT have the data param
* @ param { object } e
* /
start : function ( e ) {
OC . Upload . log ( 'start' , e , null ) ;
2014-03-19 22:05:03 +00:00
//hide the tooltip otherwise it covers the progress bar
$ ( '#upload' ) . tipsy ( 'hide' ) ;
2014-03-06 12:49:57 +00:00
} ,
submit : function ( e , data ) {
OC . Upload . rememberUpload ( data ) ;
if ( ! data . formData ) {
2014-04-10 16:07:36 +00:00
var fileDirectory = '' ;
if ( typeof data . files [ 0 ] . relativePath !== 'undefined' ) {
fileDirectory = data . files [ 0 ] . relativePath ;
}
2014-03-06 12:49:57 +00:00
// noone set update parameters, we set the minimum
data . formData = {
requesttoken : oc _requesttoken ,
2014-06-18 18:38:51 +00:00
dir : data . targetDir || FileList . getCurrentDirectory ( ) ,
2014-04-10 16:07:36 +00:00
file _directory : fileDirectory
2014-03-06 12:49:57 +00:00
} ;
}
} ,
fail : function ( e , data ) {
OC . Upload . log ( 'fail' , e , data ) ;
if ( typeof data . textStatus !== 'undefined' && data . textStatus !== 'success' ) {
if ( data . textStatus === 'abort' ) {
OC . Notification . show ( t ( 'files' , 'Upload cancelled.' ) ) ;
} else {
// HTTP connection problem
OC . Notification . show ( data . errorThrown ) ;
if ( data . result ) {
var result = JSON . parse ( data . result ) ;
if ( result && result [ 0 ] && result [ 0 ] . data && result [ 0 ] . data . code === 'targetnotfound' ) {
// abort upload of next files if any
OC . Upload . cancelUploads ( ) ;
}
2014-01-22 16:17:58 +00:00
}
}
2014-03-06 12:49:57 +00:00
//hide notification after 10 sec
setTimeout ( function ( ) {
OC . Notification . hide ( ) ;
} , 10000 ) ;
2013-09-16 12:10:19 +00:00
}
2014-03-06 12:49:57 +00:00
OC . Upload . deleteUpload ( data ) ;
} ,
/ * *
* called for every successful upload
* @ param { object } e
* @ param { object } data
* /
done : function ( e , data ) {
OC . Upload . log ( 'done' , e , data ) ;
// handle different responses (json or body from iframe for ie)
var response ;
if ( typeof data . result === 'string' ) {
response = data . result ;
} else {
//fetch response from iframe
response = data . result [ 0 ] . body . innerText ;
}
2014-05-09 12:06:59 +00:00
var result = $ . parseJSON ( response ) ;
2014-03-06 12:49:57 +00:00
delete data . jqXHR ;
2014-05-09 12:06:59 +00:00
var fu = $ ( this ) . data ( 'blueimp-fileupload' ) || $ ( this ) . data ( 'fileupload' ) ;
2014-03-06 12:49:57 +00:00
if ( result . status === 'error' && result . data && result . data . message ) {
data . textStatus = 'servererror' ;
data . errorThrown = result . data . message ;
fu . _trigger ( 'fail' , e , data ) ;
} else if ( typeof result [ 0 ] === 'undefined' ) {
data . textStatus = 'servererror' ;
data . errorThrown = t ( 'files' , 'Could not get result from server.' ) ;
fu . _trigger ( 'fail' , e , data ) ;
} else if ( result [ 0 ] . status === 'existserror' ) {
//show "file already exists" dialog
var original = result [ 0 ] ;
var replacement = data . files [ 0 ] ;
OC . dialogs . fileexists ( data , original , replacement , OC . Upload , fu ) ;
} else if ( result [ 0 ] . status !== 'success' ) {
//delete data.jqXHR;
data . textStatus = 'servererror' ;
data . errorThrown = result [ 0 ] . data . message ; // error message has been translated on server
fu . _trigger ( 'fail' , e , data ) ;
}
} ,
/ * *
* called after last upload
* @ param { object } e
* @ param { object } data
* /
stop : function ( e , data ) {
OC . Upload . log ( 'stop' , e , data ) ;
2013-09-16 12:10:19 +00:00
}
2014-03-06 12:49:57 +00:00
} ;
// initialize jquery fileupload (blueimp)
var fileupload = $ ( '#file_upload_start' ) . fileupload ( file _upload _param ) ;
window . file _upload _param = fileupload ;
if ( supportAjaxUploadWithProgress ( ) ) {
2014-08-11 22:32:46 +00:00
//remaining time
var lastUpdate = new Date ( ) . getMilliseconds ( ) ;
var lastSize = 0 ;
2014-08-13 11:18:24 +00:00
var bufferSize = 20 ;
var buffer = new Array ( ) ;
2014-08-11 22:32:46 +00:00
var bufferIndex = 0 ;
var bufferTotal = 0 ;
2014-08-13 11:18:24 +00:00
for ( var i = 0 ; i < bufferSize ; i ++ ) {
buffer [ i ] = 0 ;
}
2014-03-06 12:49:57 +00:00
// add progress handlers
fileupload . on ( 'fileuploadadd' , function ( e , data ) {
OC . Upload . log ( 'progress handle fileuploadadd' , e , data ) ;
//show cancel button
//if (data.dataType !== 'iframe') { //FIXME when is iframe used? only for ie?
// $('#uploadprogresswrapper input.stop').show();
//}
} ) ;
// add progress handlers
fileupload . on ( 'fileuploadstart' , function ( e , data ) {
OC . Upload . log ( 'progress handle fileuploadstart' , e , data ) ;
$ ( '#uploadprogresswrapper input.stop' ) . show ( ) ;
2014-08-10 20:26:03 +00:00
$ ( '#uploadprogresswrapper .label' ) . show ( ) ;
2014-05-09 12:06:59 +00:00
$ ( '#uploadprogressbar' ) . progressbar ( { value : 0 } ) ;
2014-08-11 00:37:01 +00:00
$ ( '#uploadprogressbar .ui-progressbar-value' ) . html ( '<em class="label inner"><span class="desktop">' + t ( 'files' , 'Uploading...' ) + '</span><span class="mobile">' + t ( 'files' , '...' ) + '</span></em>' ) ;
2014-08-11 22:32:46 +00:00
$ ( '#uploadprogressbar' ) . tipsy ( { gravity : 'n' , fade : true , live : true } ) ;
2014-05-23 17:02:50 +00:00
OC . Upload . _showProgressBar ( ) ;
2014-03-06 12:49:57 +00:00
} ) ;
fileupload . on ( 'fileuploadprogress' , function ( e , data ) {
OC . Upload . log ( 'progress handle fileuploadprogress' , e , data ) ;
//TODO progressbar in row
} ) ;
fileupload . on ( 'fileuploadprogressall' , function ( e , data ) {
OC . Upload . log ( 'progress handle fileuploadprogressall' , e , data ) ;
var progress = ( data . loaded / data . total ) * 100 ;
2014-08-11 22:32:46 +00:00
var thisUpdate = new Date ( ) . getMilliseconds ( ) ;
var diffUpdate = ( thisUpdate - lastUpdate ) / 1000 ; // eg. 2s
lastUpdate = thisUpdate ;
var diffSize = data . loaded - lastSize ;
lastSize = data . loaded ;
diffSize = diffSize / diffUpdate ; // apply timing factor, eg. 1mb/2s = 0.5mb/s
var remainingSeconds = ( ( data . total - data . loaded ) / diffSize ) ;
if ( remainingSeconds > 0 ) { //buffer to make it smoother
2014-08-13 11:18:24 +00:00
bufferTotal = bufferTotal - ( buffer [ bufferIndex ] ) + remainingSeconds ;
2014-08-11 22:32:46 +00:00
buffer [ bufferIndex ] = remainingSeconds ;
bufferIndex = ( bufferIndex + 1 ) % bufferSize ;
}
var smoothRemaining = ( bufferTotal / bufferSize ) ;
var date = new Date ( smoothRemaining * 1000 ) ;
2014-08-13 09:40:36 +00:00
var timeStringMobile = "" ;
var timeStringDesktop = "" ;
if ( date . getUTCHours ( ) > 0 ) {
2014-08-13 11:06:00 +00:00
timeStringDesktop = t ( 'files' , '{hours}:{minutes}:{seconds} hour{plural_s} left' , {
2014-08-13 09:40:36 +00:00
hours : date . getUTCHours ( ) ,
minutes : ( '0' + date . getUTCMinutes ( ) ) . slice ( - 2 ) ,
seconds : ( '0' + date . getUTCSeconds ( ) ) . slice ( - 2 ) ,
2014-08-13 11:06:00 +00:00
plural _s : ( date . getUTCHours ( ) == 1 && date . getUTCMinutes ( ) == 0 && date . getUTCSeconds ( ) == 0 ? "" : "s" )
2014-08-13 09:40:36 +00:00
} ) ;
2014-08-13 11:06:00 +00:00
timeStringMobile = t ( 'files' , '{hours}:{minutes}h' , {
2014-08-13 09:40:36 +00:00
hours : date . getUTCHours ( ) ,
minutes : ( '0' + date . getUTCMinutes ( ) ) . slice ( - 2 ) ,
seconds : ( '0' + date . getUTCSeconds ( ) ) . slice ( - 2 )
} ) ;
} else if ( date . getUTCMinutes ( ) > 0 ) {
2014-08-13 11:06:00 +00:00
timeStringDesktop = t ( 'files' , '{minutes}:{seconds} minute{plural_s} left' , {
2014-08-13 09:40:36 +00:00
minutes : date . getUTCMinutes ( ) ,
seconds : ( '0' + date . getUTCSeconds ( ) ) . slice ( - 2 ) ,
2014-08-13 11:06:00 +00:00
plural _s : ( date . getUTCMinutes ( ) == 1 && date . getUTCSeconds ( ) == 0 ? "" : "s" )
2014-08-13 09:40:36 +00:00
} ) ;
2014-08-13 11:06:00 +00:00
timeStringMobile = t ( 'files' , '{minutes}:{seconds}m' , {
2014-08-13 09:40:36 +00:00
minutes : date . getUTCMinutes ( ) ,
seconds : ( '0' + date . getUTCSeconds ( ) ) . slice ( - 2 )
} ) ;
} else if ( date . getUTCSeconds ( ) > 0 ) {
2014-08-13 11:06:00 +00:00
timeStringDesktop = t ( 'files' , '{seconds} second{plural_s} left' , {
2014-08-13 09:40:36 +00:00
seconds : date . getUTCSeconds ( ) ,
2014-08-13 11:06:00 +00:00
plural _s : ( date . getUTCSeconds ( ) == 1 ? "" : "s" )
2014-08-13 09:40:36 +00:00
} ) ;
timeStringMobile = t ( 'files' , '{seconds}s' , { seconds : date . getUTCSeconds ( ) } ) ;
} else {
timeStringDesktop = t ( 'files' , 'Any moment now...' ) ;
timeStringMobile = t ( 'files' , 'Soon...' ) ;
}
2014-08-13 11:06:00 +00:00
$ ( '#uploadprogressbar .label .mobile' ) . text ( timeStringMobile ) ;
$ ( '#uploadprogressbar .label .desktop' ) . text ( timeStringDesktop ) ;
2014-08-13 11:39:14 +00:00
$ ( '#uploadprogressbar' ) . attr ( 'original-title' , t ( 'files' , '{loadedSize} of {totalSize} ({bitrate})' , { loadedSize : humanFileSize ( data . loaded ) , totalSize : humanFileSize ( data . total ) , bitrate : humanFileSize ( data . bitrate ) + '/s' } ) ) ;
2014-03-06 12:49:57 +00:00
$ ( '#uploadprogressbar' ) . progressbar ( 'value' , progress ) ;
} ) ;
fileupload . on ( 'fileuploadstop' , function ( e , data ) {
OC . Upload . log ( 'progress handle fileuploadstop' , e , data ) ;
2014-05-23 17:02:50 +00:00
OC . Upload . _hideProgressBar ( ) ;
2014-03-06 12:49:57 +00:00
} ) ;
fileupload . on ( 'fileuploadfail' , function ( e , data ) {
OC . Upload . log ( 'progress handle fileuploadfail' , e , data ) ;
//if user pressed cancel hide upload progress bar and cancel button
if ( data . errorThrown === 'abort' ) {
2014-05-23 17:02:50 +00:00
OC . Upload . _hideProgressBar ( ) ;
2014-03-06 12:49:57 +00:00
}
} ) ;
2013-09-16 12:10:19 +00:00
2013-10-22 16:11:03 +00:00
}
2013-08-12 10:33:22 +00:00
}
2014-03-06 12:49:57 +00:00
$ . assocArraySize = function ( obj ) {
// http://stackoverflow.com/a/6700/11236
var size = 0 , key ;
for ( key in obj ) {
if ( obj . hasOwnProperty ( key ) ) {
size ++ ;
}
}
return size ;
} ;
2013-06-26 20:51:38 +00:00
2014-03-06 12:49:57 +00:00
// warn user not to leave the page while upload is in progress
$ ( window ) . on ( 'beforeunload' , function ( e ) {
if ( OC . Upload . isProcessing ( ) ) {
return t ( 'files' , 'File upload is in progress. Leaving the page now will cancel the upload.' ) ;
}
} ) ;
2013-08-12 10:33:22 +00:00
2014-03-06 12:49:57 +00:00
//add multiply file upload attribute to all browsers except konqueror (which crashes when it's used)
if ( navigator . userAgent . search ( /konqueror/i ) === - 1 ) {
$ ( '#file_upload_start' ) . attr ( 'multiple' , 'multiple' ) ;
}
2013-08-12 10:33:22 +00:00
2014-03-06 12:49:57 +00:00
$ ( document ) . click ( function ( ev ) {
// do not close when clicking in the dropdown
if ( $ ( ev . target ) . closest ( '#new' ) . length ) {
return ;
2013-08-15 22:31:27 +00:00
}
2014-03-06 12:49:57 +00:00
$ ( '#new>ul' ) . hide ( ) ;
$ ( '#new' ) . removeClass ( 'active' ) ;
if ( $ ( '#new .error' ) . length > 0 ) {
$ ( '#new .error' ) . tipsy ( 'hide' ) ;
}
$ ( '#new li' ) . each ( function ( i , element ) {
if ( $ ( element ) . children ( 'p' ) . length === 0 ) {
$ ( element ) . children ( 'form' ) . remove ( ) ;
2014-05-09 12:06:59 +00:00
$ ( element ) . append ( '<p>' + $ ( element ) . data ( 'text' ) + '</p>' ) ;
2014-03-06 12:49:57 +00:00
}
} ) ;
2013-08-15 22:31:27 +00:00
} ) ;
2014-03-06 12:49:57 +00:00
$ ( '#new' ) . click ( function ( event ) {
event . stopPropagation ( ) ;
} ) ;
$ ( '#new>a' ) . click ( function ( ) {
$ ( '#new>ul' ) . toggle ( ) ;
$ ( '#new' ) . toggleClass ( 'active' ) ;
} ) ;
$ ( '#new li' ) . click ( function ( ) {
if ( $ ( this ) . children ( 'p' ) . length === 0 ) {
return ;
2013-10-22 16:11:03 +00:00
}
2014-03-06 12:49:57 +00:00
$ ( '#new .error' ) . tipsy ( 'hide' ) ;
2013-10-22 16:11:03 +00:00
2014-05-09 12:06:59 +00:00
$ ( '#new li' ) . each ( function ( i , element ) {
2014-03-06 12:49:57 +00:00
if ( $ ( element ) . children ( 'p' ) . length === 0 ) {
$ ( element ) . children ( 'form' ) . remove ( ) ;
2014-05-09 12:06:59 +00:00
$ ( element ) . append ( '<p>' + $ ( element ) . data ( 'text' ) + '</p>' ) ;
2013-10-22 16:11:03 +00:00
}
2014-03-06 12:49:57 +00:00
} ) ;
2014-05-09 12:06:59 +00:00
var type = $ ( this ) . data ( 'type' ) ;
var text = $ ( this ) . children ( 'p' ) . text ( ) ;
$ ( this ) . data ( 'text' , text ) ;
2014-03-06 12:49:57 +00:00
$ ( this ) . children ( 'p' ) . remove ( ) ;
// add input field
var form = $ ( '<form></form>' ) ;
var input = $ ( '<input type="text">' ) ;
var newName = $ ( this ) . attr ( 'data-newname' ) || '' ;
if ( newName ) {
input . val ( newName ) ;
}
form . append ( input ) ;
$ ( this ) . append ( form ) ;
var lastPos ;
var checkInput = function ( ) {
var filename = input . val ( ) ;
if ( type === 'web' && filename . length === 0 ) {
throw t ( 'files' , 'URL cannot be empty' ) ;
2014-05-09 12:06:59 +00:00
} else if ( type !== 'web' && ! Files . isFileNameValid ( filename ) ) {
2014-03-06 12:49:57 +00:00
// Files.isFileNameValid(filename) throws an exception itself
} else if ( FileList . inList ( filename ) ) {
throw t ( 'files' , '{new_name} already exists' , { new _name : filename } ) ;
2013-10-22 16:11:03 +00:00
} else {
2014-03-06 12:49:57 +00:00
return true ;
2013-10-22 16:11:03 +00:00
}
2014-03-06 12:49:57 +00:00
} ;
// verify filename on typing
input . keyup ( function ( event ) {
try {
checkInput ( ) ;
input . tipsy ( 'hide' ) ;
input . removeClass ( 'error' ) ;
} catch ( error ) {
input . attr ( 'title' , error ) ;
input . tipsy ( { gravity : 'w' , trigger : 'manual' } ) ;
input . tipsy ( 'show' ) ;
input . addClass ( 'error' ) ;
}
} ) ;
input . focus ( ) ;
// pre select name up to the extension
lastPos = newName . lastIndexOf ( '.' ) ;
if ( lastPos === - 1 ) {
lastPos = newName . length ;
}
input . selectRange ( 0 , lastPos ) ;
form . submit ( function ( event ) {
event . stopPropagation ( ) ;
event . preventDefault ( ) ;
try {
checkInput ( ) ;
var newname = input . val ( ) ;
if ( FileList . lastAction ) {
FileList . lastAction ( ) ;
}
2014-05-08 20:06:30 +00:00
var name = FileList . getUniqueName ( newname ) ;
2014-03-06 12:49:57 +00:00
if ( newname !== name ) {
FileList . checkName ( name , newname , true ) ;
var hidden = true ;
} else {
var hidden = false ;
}
switch ( type ) {
case 'file' :
$ . post (
OC . filePath ( 'files' , 'ajax' , 'newfile.php' ) ,
2014-05-09 12:06:59 +00:00
{
2014-05-08 20:06:30 +00:00
dir : FileList . getCurrentDirectory ( ) ,
2014-05-09 12:06:59 +00:00
filename : name
} ,
2014-03-06 12:49:57 +00:00
function ( result ) {
if ( result . status === 'success' ) {
2014-04-04 14:11:31 +00:00
FileList . add ( result . data , { hidden : hidden , animate : true } ) ;
2014-03-06 12:49:57 +00:00
} else {
OC . dialogs . alert ( result . data . message , t ( 'core' , 'Could not create file' ) ) ;
}
2013-10-22 16:11:03 +00:00
}
2014-03-06 12:49:57 +00:00
) ;
break ;
case 'folder' :
$ . post (
OC . filePath ( 'files' , 'ajax' , 'newfolder.php' ) ,
2014-05-09 12:06:59 +00:00
{
2014-05-08 20:06:30 +00:00
dir : FileList . getCurrentDirectory ( ) ,
2014-05-09 12:06:59 +00:00
foldername : name
} ,
2014-03-06 12:49:57 +00:00
function ( result ) {
if ( result . status === 'success' ) {
2014-04-04 14:11:31 +00:00
FileList . add ( result . data , { hidden : hidden , animate : true } ) ;
2014-03-06 12:49:57 +00:00
} else {
OC . dialogs . alert ( result . data . message , t ( 'core' , 'Could not create folder' ) ) ;
}
2013-10-22 16:11:03 +00:00
}
2014-03-06 12:49:57 +00:00
) ;
break ;
case 'web' :
2014-05-09 12:06:59 +00:00
if ( name . substr ( 0 , 8 ) !== 'https://' && name . substr ( 0 , 7 ) !== 'http://' ) {
2014-03-06 12:49:57 +00:00
name = 'http://' + name ;
2013-08-15 22:31:27 +00:00
}
2014-05-09 12:06:59 +00:00
var localName = name ;
if ( localName . substr ( localName . length - 1 , 1 ) === '/' ) { //strip /
localName = localName . substr ( 0 , localName . length - 1 ) ;
2014-03-06 12:49:57 +00:00
}
2014-05-09 12:06:59 +00:00
if ( localName . indexOf ( '/' ) ) { //use last part of url
localName = localName . split ( '/' ) . pop ( ) ;
2014-03-06 12:49:57 +00:00
} else { //or the domain
2014-05-09 12:06:59 +00:00
localName = ( localName . match ( /:\/\/(.[^\/]+)/ ) [ 1 ] ) . replace ( 'www.' , '' ) ;
2014-03-06 12:49:57 +00:00
}
2014-05-08 20:06:30 +00:00
localName = FileList . getUniqueName ( localName ) ;
2013-10-22 16:11:03 +00:00
//IE < 10 does not fire the necessary events for the progress bar.
if ( $ ( 'html.lte9' ) . length === 0 ) {
2014-05-09 12:06:59 +00:00
$ ( '#uploadprogressbar' ) . progressbar ( { value : 0 } ) ;
2014-05-23 17:02:50 +00:00
OC . Upload . _showProgressBar ( ) ;
2013-10-22 16:11:03 +00:00
}
2014-03-06 12:49:57 +00:00
2014-05-09 12:06:59 +00:00
var eventSource = new OC . EventSource (
OC . filePath ( 'files' , 'ajax' , 'newfile.php' ) ,
{
2014-05-08 20:06:30 +00:00
dir : FileList . getCurrentDirectory ( ) ,
2014-05-09 12:06:59 +00:00
source : name ,
filename : localName
}
) ;
eventSource . listen ( 'progress' , function ( progress ) {
2014-03-06 12:49:57 +00:00
//IE < 10 does not fire the necessary events for the progress bar.
if ( $ ( 'html.lte9' ) . length === 0 ) {
$ ( '#uploadprogressbar' ) . progressbar ( 'value' , progress ) ;
}
} ) ;
2014-05-09 12:06:59 +00:00
eventSource . listen ( 'success' , function ( data ) {
2013-10-28 19:22:06 +00:00
var file = data ;
2014-05-23 17:02:50 +00:00
OC . Upload . _hideProgressBar ( ) ;
2013-10-28 19:22:06 +00:00
2014-04-04 14:11:31 +00:00
FileList . add ( file , { hidden : hidden , animate : true } ) ;
2014-03-06 12:49:57 +00:00
} ) ;
2014-05-09 12:06:59 +00:00
eventSource . listen ( 'error' , function ( error ) {
2014-05-23 17:02:50 +00:00
OC . Upload . _hideProgressBar ( ) ;
2014-03-06 12:49:57 +00:00
var message = ( error && error . message ) || t ( 'core' , 'Error fetching URL' ) ;
OC . Notification . show ( message ) ;
//hide notification after 10 sec
setTimeout ( function ( ) {
OC . Notification . hide ( ) ;
} , 10000 ) ;
} ) ;
break ;
}
2014-05-09 12:06:59 +00:00
var li = form . parent ( ) ;
2014-03-06 12:49:57 +00:00
form . remove ( ) ;
/* workaround for IE 9&10 click event trap, 2 lines: */
$ ( 'input' ) . first ( ) . focus ( ) ;
$ ( '#content' ) . focus ( ) ;
2014-05-09 12:06:59 +00:00
li . append ( '<p>' + li . data ( 'text' ) + '</p>' ) ;
2014-03-06 12:49:57 +00:00
$ ( '#new>a' ) . click ( ) ;
} catch ( error ) {
input . attr ( 'title' , error ) ;
input . tipsy ( { gravity : 'w' , trigger : 'manual' } ) ;
input . tipsy ( 'show' ) ;
input . addClass ( 'error' ) ;
2013-10-22 16:11:03 +00:00
}
2014-03-06 12:49:57 +00:00
} ) ;
2013-06-26 20:51:38 +00:00
} ) ;
2014-03-06 12:49:57 +00:00
window . file _upload _param = file _upload _param ;
return file _upload _param ;
}
} ;
$ ( document ) . ready ( function ( ) {
OC . Upload . init ( ) ;
2013-06-26 20:51:38 +00:00
} ) ;
2014-03-06 12:49:57 +00:00
2014-04-07 20:20:44 +00:00