2013-08-14 19:49:45 +04:00
/ * *
2013-09-08 12:41:20 +04: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 19:49:45 +04:00
* /
2013-09-16 16:10:19 +04: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 12:19:54 +04:00
function supportAjaxUploadWithProgress ( ) {
return supportFileAPI ( ) && supportAjaxUploadProgressEvents ( ) && supportFormData ( ) ;
2013-08-14 19:49:45 +04:00
2013-09-05 12:19:54 +04:00
// Is the File API supported?
function supportFileAPI ( ) {
var fi = document . createElement ( 'INPUT' ) ;
fi . type = 'file' ;
return 'files' in fi ;
2013-10-23 00:39:28 +04:00
}
2013-09-05 12:19:54 +04:00
// Are progress events supported?
function supportAjaxUploadProgressEvents ( ) {
var xhr = new XMLHttpRequest ( ) ;
return ! ! ( xhr && ( 'upload' in xhr ) && ( 'onprogress' in xhr . upload ) ) ;
2013-10-23 00:39:28 +04:00
}
2013-09-05 12:19:54 +04:00
// Is FormData supported?
function supportFormData ( ) {
return ! ! window . FormData ;
}
}
2013-08-16 13:40:55 +04:00
2013-09-08 12:41:20 +04:00
/ * *
* keeps track of uploads in progress and implements callbacks for the conflicts dialog
2013-09-19 13:11:22 +04:00
* @ type { OC . Upload }
2013-09-08 12:41:20 +04:00
* /
2013-08-16 13:40:55 +04:00
OC . Upload = {
2013-09-07 00:40:10 +04:00
_uploads : [ ] ,
2013-09-08 12:41:20 +04:00
/ * *
* deletes the jqHXR object from a data selection
2013-09-19 13:11:22 +04:00
* @ param { object } data
2013-09-08 12:41:20 +04:00
* /
2013-09-07 00:40:10 +04:00
deleteUpload : function ( data ) {
delete data . jqXHR ;
} ,
2013-09-08 12:41:20 +04:00
/ * *
* cancels all uploads
* /
2013-08-16 13:40:55 +04:00
cancelUploads : function ( ) {
2013-09-18 16:39:39 +04:00
this . log ( 'canceling uploads' ) ;
2013-10-22 20:11:03 +04:00
jQuery . each ( this . _uploads , function ( i , jqXHR ) {
2013-09-07 00:40:10 +04:00
jqXHR . abort ( ) ;
2013-08-16 13:40:55 +04:00
} ) ;
2013-09-07 00:40:10 +04:00
this . _uploads = [ ] ;
2013-06-27 00:51:38 +04:00
} ,
2013-10-22 20:11:03 +04:00
rememberUpload : function ( jqXHR ) {
2013-09-07 00:40:10 +04:00
if ( jqXHR ) {
this . _uploads . push ( jqXHR ) ;
2013-06-27 00:51:38 +04:00
}
2013-08-16 13:40:55 +04:00
} ,
2013-09-08 12:41:20 +04:00
/ * *
* Checks the currently known uploads .
* returns true if any hxr has the state 'pending'
2013-09-19 13:11:22 +04:00
* @ returns { boolean }
2013-09-08 12:41:20 +04:00
* /
2013-10-22 20:11:03 +04:00
isProcessing : function ( ) {
2013-09-07 00:40:10 +04:00
var count = 0 ;
2013-10-22 20:11:03 +04:00
jQuery . each ( this . _uploads , function ( i , data ) {
2013-09-07 00:40:10 +04:00
if ( data . state ( ) === 'pending' ) {
count ++ ;
}
2013-08-16 13:40:55 +04:00
} ) ;
2013-09-07 00:40:10 +04:00
return count > 0 ;
2013-06-27 00:51:38 +04:00
} ,
2013-09-08 12:41:20 +04:00
/ * *
* callback for the conflicts dialog
2013-09-19 13:11:22 +04:00
* @ param { object } data
2013-09-08 12:41:20 +04:00
* /
2013-09-05 19:46:19 +04:00
onCancel : function ( data ) {
2013-09-07 00:40:10 +04:00
this . cancelUploads ( ) ;
2013-08-12 14:33:22 +04:00
} ,
2013-09-08 12:41:20 +04:00
/ * *
* callback for the conflicts dialog
* calls onSkip , onReplace or onAutorename for each conflict
2013-09-19 13:11:22 +04:00
* @ param { object } conflicts - list of conflict elements
2013-09-08 12:41:20 +04:00
* /
2013-09-05 19:46:19 +04: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 12:41:20 +04:00
/ * *
* handle skipping an upload
2013-09-19 13:11:22 +04:00
* @ param { object } data
2013-09-08 12:41:20 +04:00
* /
2013-10-22 20:11:03 +04:00
onSkip : function ( data ) {
2013-09-18 16:39:39 +04:00
this . log ( 'skip' , null , data ) ;
2013-09-07 00:40:10 +04:00
this . deleteUpload ( data ) ;
2013-06-27 00:51:38 +04:00
} ,
2013-09-08 12:41:20 +04:00
/ * *
* handle replacing a file on the server with an uploaded file
2013-09-19 13:11:22 +04:00
* @ param { object } data
2013-09-08 12:41:20 +04:00
* /
2013-10-22 20:11:03 +04:00
onReplace : function ( data ) {
2013-09-18 16:39:39 +04:00
this . log ( 'replace' , null , data ) ;
2013-10-22 20:11:03 +04:00
if ( data . data ) {
2013-10-10 17:54:00 +04:00
data . data . append ( 'resolution' , 'replace' ) ;
} else {
2013-10-22 20:11:03 +04:00
data . formData . push ( { name : 'resolution' , value : 'replace' } ) ; //hack for ie8
2013-10-10 17:54:00 +04:00
}
2013-08-12 14:33:22 +04:00
data . submit ( ) ;
2013-06-27 00:51:38 +04:00
} ,
2013-09-08 12:41:20 +04:00
/ * *
* handle uploading a file and letting the server decide a new name
2013-09-19 13:11:22 +04:00
* @ param { object } data
2013-09-08 12:41:20 +04:00
* /
2013-10-22 20:11:03 +04:00
onAutorename : function ( data ) {
2013-09-18 16:39:39 +04:00
this . log ( 'autorename' , null , data ) ;
2013-09-07 01:44:40 +04:00
if ( data . data ) {
data . data . append ( 'resolution' , 'autorename' ) ;
} else {
2013-10-22 20:11:03 +04:00
data . formData . push ( { name : 'resolution' , value : 'autorename' } ) ; //hack for ie8
2013-09-07 01:44:40 +04:00
}
2013-08-12 14:33:22 +04:00
data . submit ( ) ;
2013-08-16 13:40:55 +04:00
} ,
2013-09-18 16:39:39 +04: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 16:29:00 +04:00
} ,
2013-09-08 12:41:20 +04:00
/ * *
* TODO checks the list of existing files prior to uploading and shows a simple dialog to choose
2013-09-19 13:13:11 +04:00
* skip all , replace all or choose which files to keep
2013-09-19 13:11:22 +04: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 12:41:20 +04:00
* /
2013-10-22 20:11:03 +04:00
checkExistingFiles : function ( selection , callbacks ) {
2013-09-08 12:41:20 +04:00
// TODO check filelist before uploading and show dialog on conflicts, use callbacks
2013-08-22 16:29:00 +04:00
callbacks . onNoConflicts ( selection ) ;
2013-08-12 14:33:22 +04:00
}
} ;
2013-06-27 00:51:38 +04:00
2013-08-12 14:33:22 +04:00
$ ( document ) . ready ( function ( ) {
2013-06-27 00:51:38 +04:00
2013-09-18 16:19:58 +04:00
if ( $ ( '#file_upload_start' ) . exists ( ) ) {
2013-09-16 16:10:19 +04:00
var file _upload _param = {
dropZone : $ ( '#content' ) , // restrict dropZone to content div
2013-09-18 16:19:58 +04:00
autoUpload : false ,
sequentialUploads : true ,
2013-09-16 16:10:19 +04:00
//singleFileUploads is on by default, so the data.files array will always have length 1
2013-09-18 16:19:58 +04:00
/ * *
* 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
2013-09-19 13:11:22 +04:00
* @ param { object } e
* @ param { object } data
* @ returns { boolean }
2013-09-18 16:19:58 +04:00
* /
2013-09-16 16:10:19 +04:00
add : function ( e , data ) {
2013-09-18 16:39:39 +04:00
OC . Upload . log ( 'add' , e , data ) ;
2013-09-18 16:19:58 +04:00
var that = $ ( this ) ;
2013-08-16 13:40:55 +04:00
2013-09-18 16:19:58 +04: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
2013-08-16 13:40:55 +04:00
2013-09-18 16:19:58 +04: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 ;
2013-08-16 13:40:55 +04:00
2013-09-18 16:19:58 +04:00
// add uploads
2013-10-22 20:11:03 +04:00
if ( selection . uploads . length < selection . filesToUpload ) {
2013-09-18 16:19:58 +04:00
// remember upload
selection . uploads . push ( data ) ;
}
2013-08-22 16:29:00 +04:00
2013-09-18 16:19:58 +04:00
//examine file
var file = data . files [ 0 ] ;
2013-08-22 16:29:00 +04:00
2013-09-18 16:19:58 +04:00
if ( file . type === '' && file . size === 4096 ) {
2013-09-16 16:10:19 +04:00
data . textStatus = 'dirorzero' ;
2013-09-18 16:19:58 +04:00
data . errorThrown = t ( 'files' , 'Unable to upload {filename} as it is a directory or has 0 bytes' ,
{ filename : file . name }
) ;
2013-08-16 02:31:27 +04:00
}
2013-08-22 16:29:00 +04:00
2013-09-18 16:19:58 +04:00
// add size
selection . totalBytes += file . size ;
2013-08-22 16:29:00 +04:00
2013-12-08 19:17:35 +04:00
// check PHP upload limit
if ( selection . totalBytes > $ ( '#upload_limit' ) . val ( ) ) {
2013-12-08 11:41:20 +04:00
data . textStatus = 'sizeexceedlimit' ;
2013-12-11 11:40:58 +04:00
data . errorThrown = t ( 'files' , 'Total file size {size1} exceeds upload limit {size2}' ) . replace ( '{size1}' , humanFileSize ( selection . totalBytes ) ) . replace ( '{size2}' , humanFileSize ( $ ( '#upload_limit' ) . val ( ) ) ) ;
2013-09-18 16:19:58 +04:00
}
2013-12-08 19:17:35 +04:00
// check free space
if ( selection . totalBytes > $ ( '#free_space' ) . val ( ) ) {
data . textStatus = 'notenoughspace' ;
2013-12-11 11:40:58 +04:00
data . errorThrown = t ( 'files' , 'Not enough free space, you are uploading {size1} but only {size2} is left' ) . replace ( '{size1}' , humanFileSize ( selection . totalBytes ) ) . replace ( '{size2}' , humanFileSize ( $ ( '#free_space' ) . val ( ) ) ) ;
2013-12-08 19:17:35 +04:00
}
2013-08-22 16:29:00 +04:00
2013-09-18 16:19:58 +04:00
// end upload for whole selection on error
if ( data . errorThrown ) {
// trigger fileupload fail
var fu = that . data ( 'blueimp-fileupload' ) || that . data ( 'fileupload' ) ;
2013-09-16 16:10:19 +04:00
fu . _trigger ( 'fail' , e , data ) ;
return false ; //don't upload anything
2013-08-16 02:31:27 +04:00
}
2013-08-22 16:29:00 +04:00
2013-09-18 16:19:58 +04:00
// check existing files when all is collected
if ( selection . uploads . length >= selection . filesToUpload ) {
2013-08-12 14:33:22 +04:00
2013-09-18 16:19:58 +04:00
//remove our selection hack:
delete data . originalFiles . selection ;
2013-06-27 00:51:38 +04:00
2013-09-18 16:19:58 +04:00
var callbacks = {
2013-08-22 16:29:00 +04:00
2013-09-18 16:19:58 +04:00
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-27 00:51:38 +04:00
2013-09-18 16:19:58 +04:00
OC . Upload . checkExistingFiles ( selection , callbacks ) ;
2013-08-12 14:33:22 +04:00
2013-08-28 01:53:04 +04:00
}
2013-06-27 00:51:38 +04:00
2013-09-18 16:19:58 +04:00
return true ; // continue adding files
} ,
/ * *
* called after the first add , does NOT have the data param
2013-09-19 13:11:22 +04:00
* @ param { object } e
2013-09-18 16:19:58 +04:00
* /
start : function ( e ) {
2013-09-18 16:39:39 +04:00
OC . Upload . log ( 'start' , e , null ) ;
2013-09-16 16:10:19 +04:00
} ,
submit : function ( e , data ) {
2013-09-18 16:19:58 +04:00
OC . Upload . rememberUpload ( data ) ;
2013-09-16 16:10:19 +04:00
if ( ! data . formData ) {
// noone set update parameters, we set the minimum
data . formData = {
requesttoken : oc _requesttoken ,
dir : $ ( '#dir' ) . val ( )
} ;
}
} ,
fail : function ( e , data ) {
2013-09-18 16:39:39 +04:00
OC . Upload . log ( 'fail' , e , data ) ;
2013-09-16 16:10:19 +04:00
if ( typeof data . textStatus !== 'undefined' && data . textStatus !== 'success' ) {
if ( data . textStatus === 'abort' ) {
2013-11-08 14:22:08 +04:00
OC . Notification . show ( t ( 'files' , 'Upload cancelled.' ) ) ;
2013-09-16 16:10:19 +04:00
} else {
// HTTP connection problem
2013-11-08 14:22:08 +04:00
OC . Notification . show ( data . errorThrown ) ;
2013-09-16 16:10:19 +04:00
}
2013-11-08 14:22:08 +04:00
//hide notification after 10 sec
2013-09-16 16:10:19 +04:00
setTimeout ( function ( ) {
2013-11-08 14:22:08 +04:00
OC . Notification . hide ( ) ;
} , 10000 ) ;
2013-09-16 16:10:19 +04:00
}
2013-09-18 16:19:58 +04:00
OC . Upload . deleteUpload ( data ) ;
2013-09-16 16:10:19 +04:00
} ,
/ * *
* called for every successful upload
2013-09-19 13:11:22 +04:00
* @ param { object } e
* @ param { object } data
2013-09-16 16:10:19 +04:00
* /
done : function ( e , data ) {
2013-09-18 16:39:39 +04:00
OC . Upload . log ( 'done' , e , data ) ;
2013-09-16 16:10:19 +04:00
// handle different responses (json or body from iframe for ie)
var response ;
if ( typeof data . result === 'string' ) {
response = data . result ;
2013-08-12 14:33:22 +04:00
} else {
2013-09-16 16:10:19 +04:00
//fetch response from iframe
response = data . result [ 0 ] . body . innerText ;
2013-08-12 14:33:22 +04:00
}
2013-09-16 16:10:19 +04:00
var result = $ . parseJSON ( response ) ;
2013-06-27 00:51:38 +04:00
2013-09-18 16:19:58 +04:00
delete data . jqXHR ;
2013-10-29 19:00:34 +04:00
if ( result . status === 'error' && result . data && result . data . message ) {
data . textStatus = 'servererror' ;
data . errorThrown = result . data . message ;
var fu = $ ( this ) . data ( 'blueimp-fileupload' ) || $ ( this ) . data ( 'fileupload' ) ;
fu . _trigger ( 'fail' , e , data ) ;
} else if ( typeof result [ 0 ] === 'undefined' ) {
2013-09-18 16:19:58 +04:00
data . textStatus = 'servererror' ;
data . errorThrown = t ( 'files' , 'Could not get result from server.' ) ;
var fu = $ ( this ) . data ( 'blueimp-fileupload' ) || $ ( this ) . data ( 'fileupload' ) ;
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 ] ;
var fu = $ ( this ) . data ( 'blueimp-fileupload' ) || $ ( this ) . data ( 'fileupload' ) ;
OC . dialogs . fileexists ( data , original , replacement , OC . Upload , fu ) ;
} else if ( result [ 0 ] . status !== 'success' ) {
//delete data.jqXHR;
2013-09-16 16:10:19 +04:00
data . textStatus = 'servererror' ;
2013-10-08 17:03:24 +04:00
data . errorThrown = result [ 0 ] . data . message ; // error message has been translated on server
2013-09-16 16:10:19 +04:00
var fu = $ ( this ) . data ( 'blueimp-fileupload' ) || $ ( this ) . data ( 'fileupload' ) ;
fu . _trigger ( 'fail' , e , data ) ;
}
} ,
/ * *
* called after last upload
2013-09-19 13:11:22 +04:00
* @ param { object } e
* @ param { object } data
2013-09-16 16:10:19 +04:00
* /
stop : function ( e , data ) {
2013-09-18 16:39:39 +04:00
OC . Upload . log ( 'stop' , e , data ) ;
2013-08-12 14:33:22 +04:00
}
2013-09-16 16:10:19 +04:00
} ;
2013-06-27 00:51:38 +04:00
2013-09-05 12:19:54 +04:00
// initialize jquery fileupload (blueimp)
var fileupload = $ ( '#file_upload_start' ) . fileupload ( file _upload _param ) ;
2013-09-05 12:31:43 +04:00
window . file _upload _param = fileupload ;
2013-09-16 16:10:19 +04:00
2013-10-22 20:11:03 +04:00
if ( supportAjaxUploadWithProgress ( ) ) {
2013-06-27 00:51:38 +04:00
2013-09-05 12:19:54 +04:00
// add progress handlers
fileupload . on ( 'fileuploadadd' , function ( e , data ) {
2013-09-18 16:39:39 +04:00
OC . Upload . log ( 'progress handle fileuploadadd' , e , data ) ;
2013-09-05 12:19:54 +04:00
//show cancel button
2013-10-22 20:11:03 +04:00
//if (data.dataType !== 'iframe') { //FIXME when is iframe used? only for ie?
2013-09-05 12:19:54 +04:00
// $('#uploadprogresswrapper input.stop').show();
//}
} ) ;
// add progress handlers
fileupload . on ( 'fileuploadstart' , function ( e , data ) {
2013-09-18 16:39:39 +04:00
OC . Upload . log ( 'progress handle fileuploadstart' , e , data ) ;
2013-09-05 12:19:54 +04:00
$ ( '#uploadprogresswrapper input.stop' ) . show ( ) ;
$ ( '#uploadprogressbar' ) . progressbar ( { value : 0 } ) ;
$ ( '#uploadprogressbar' ) . fadeIn ( ) ;
} ) ;
fileupload . on ( 'fileuploadprogress' , function ( e , data ) {
2013-09-18 16:39:39 +04:00
OC . Upload . log ( 'progress handle fileuploadprogress' , e , data ) ;
2013-09-05 12:19:54 +04:00
//TODO progressbar in row
} ) ;
fileupload . on ( 'fileuploadprogressall' , function ( e , data ) {
2013-09-18 16:39:39 +04:00
OC . Upload . log ( 'progress handle fileuploadprogressall' , e , data ) ;
2013-09-05 12:19:54 +04:00
var progress = ( data . loaded / data . total ) * 100 ;
$ ( '#uploadprogressbar' ) . progressbar ( 'value' , progress ) ;
} ) ;
fileupload . on ( 'fileuploadstop' , function ( e , data ) {
2013-09-18 16:39:39 +04:00
OC . Upload . log ( 'progress handle fileuploadstop' , e , data ) ;
2013-09-08 12:41:20 +04:00
2013-09-06 20:16:40 +04:00
$ ( '#uploadprogresswrapper input.stop' ) . fadeOut ( ) ;
$ ( '#uploadprogressbar' ) . fadeOut ( ) ;
2013-11-06 13:15:05 +04:00
Files . updateStorageStatistics ( ) ;
2013-09-05 12:19:54 +04:00
} ) ;
fileupload . on ( 'fileuploadfail' , function ( e , data ) {
2013-09-18 16:39:39 +04:00
OC . Upload . log ( 'progress handle fileuploadfail' , e , data ) ;
2013-09-05 12:19:54 +04:00
//if user pressed cancel hide upload progress bar and cancel button
if ( data . errorThrown === 'abort' ) {
$ ( '#uploadprogresswrapper input.stop' ) . fadeOut ( ) ;
$ ( '#uploadprogressbar' ) . fadeOut ( ) ;
}
} ) ;
2013-09-16 16:10:19 +04:00
2013-09-05 12:19:54 +04:00
} else {
console . log ( 'skipping file progress because your browser is broken' ) ;
}
2013-08-12 14:33:22 +04:00
}
2013-09-16 16:10:19 +04:00
2013-08-12 14:33:22 +04:00
$ . assocArraySize = function ( obj ) {
// http://stackoverflow.com/a/6700/11236
var size = 0 , key ;
for ( key in obj ) {
2013-10-22 20:11:03 +04:00
if ( obj . hasOwnProperty ( key ) ) {
size ++ ;
}
2013-08-12 14:33:22 +04:00
}
return size ;
} ;
// warn user not to leave the page while upload is in progress
2013-08-21 16:58:28 +04:00
$ ( window ) . on ( 'beforeunload' , function ( e ) {
if ( OC . Upload . isProcessing ( ) ) {
2013-08-12 14:33:22 +04:00
return t ( 'files' , 'File upload is in progress. Leaving the page now will cancel the upload.' ) ;
}
2013-06-27 00:51:38 +04:00
} ) ;
2013-08-12 14:33:22 +04:00
//add multiply file upload attribute to all browsers except konqueror (which crashes when it's used)
2013-10-22 20:11:03 +04:00
if ( navigator . userAgent . search ( /konqueror/i ) === - 1 ) {
$ ( '#file_upload_start' ) . attr ( 'multiple' , 'multiple' ) ;
2013-08-12 14:33:22 +04:00
}
//if the breadcrumb is to long, start by replacing foldernames with '...' except for the current folder
2013-08-16 02:31:27 +04:00
var crumb = $ ( 'div.crumb' ) . first ( ) ;
2013-10-22 20:11:03 +04:00
while ( $ ( 'div.controls' ) . height ( ) > 40 && crumb . next ( 'div.crumb' ) . length > 0 ) {
2013-08-12 14:33:22 +04:00
crumb . children ( 'a' ) . text ( '...' ) ;
2013-10-22 20:11:03 +04:00
crumb = crumb . next ( 'div.crumb' ) ;
2013-08-12 14:33:22 +04:00
}
//if that isn't enough, start removing items from the breacrumb except for the current folder and it's parent
2013-10-22 20:11:03 +04:00
var crumb = $ ( 'div.crumb' ) . first ( ) ;
var next = crumb . next ( 'div.crumb' ) ;
while ( $ ( 'div.controls' ) . height ( ) > 40 && next . next ( 'div.crumb' ) . length > 0 ) {
2013-08-12 14:33:22 +04:00
crumb . remove ( ) ;
2013-10-22 20:11:03 +04:00
crumb = next ;
next = crumb . next ( 'div.crumb' ) ;
2013-06-27 00:51:38 +04:00
}
2013-08-12 14:33:22 +04:00
//still not enough, start shorting down the current folder name
2013-08-16 02:31:27 +04:00
var crumb = $ ( 'div.crumb>a' ) . last ( ) ;
2013-10-22 20:11:03 +04:00
while ( $ ( 'div.controls' ) . height ( ) > 40 && crumb . text ( ) . length > 6 ) {
var text = crumb . text ( ) ;
text = text . substr ( 0 , text . length - 6 ) + '...' ;
2013-08-12 14:33:22 +04:00
crumb . text ( text ) ;
}
2013-10-30 20:55:41 +04:00
$ ( document ) . click ( function ( ev ) {
// do not close when clicking in the dropdown
if ( $ ( ev . target ) . closest ( '#new' ) . length ) {
return ;
}
2013-08-12 14:33:22 +04:00
$ ( '#new>ul' ) . hide ( ) ;
$ ( '#new' ) . removeClass ( 'active' ) ;
2013-10-22 20:11:03 +04:00
if ( $ ( '#new .error' ) . length > 0 ) {
$ ( '#new .error' ) . tipsy ( 'hide' ) ;
}
$ ( '#new li' ) . each ( function ( i , element ) {
if ( $ ( element ) . children ( 'p' ) . length === 0 ) {
2013-08-12 14:33:22 +04:00
$ ( element ) . children ( 'form' ) . remove ( ) ;
2013-08-16 02:31:27 +04:00
$ ( element ) . append ( '<p>' + $ ( element ) . data ( 'text' ) + '</p>' ) ;
2013-08-12 14:33:22 +04:00
}
} ) ;
} ) ;
2013-10-22 20:11:03 +04:00
$ ( '#new' ) . click ( function ( event ) {
2013-08-22 02:09:43 +04:00
event . stopPropagation ( ) ;
} ) ;
2013-10-22 20:11:03 +04:00
$ ( '#new>a' ) . click ( function ( ) {
2013-08-22 02:09:43 +04:00
$ ( '#new>ul' ) . toggle ( ) ;
$ ( '#new' ) . toggleClass ( 'active' ) ;
} ) ;
2013-10-22 20:11:03 +04:00
$ ( '#new li' ) . click ( function ( ) {
if ( $ ( this ) . children ( 'p' ) . length === 0 ) {
2013-08-12 14:33:22 +04:00
return ;
}
2013-10-22 20:11:03 +04:00
$ ( '#new .error' ) . tipsy ( 'hide' ) ;
2013-06-27 00:51:38 +04:00
2013-10-22 20:11:03 +04:00
$ ( '#new li' ) . each ( function ( i , element ) {
if ( $ ( element ) . children ( 'p' ) . length === 0 ) {
2013-08-16 02:31:27 +04:00
$ ( element ) . children ( 'form' ) . remove ( ) ;
$ ( element ) . append ( '<p>' + $ ( element ) . data ( 'text' ) + '</p>' ) ;
}
} ) ;
2013-06-27 00:51:38 +04:00
2013-08-16 02:31:27 +04:00
var type = $ ( this ) . data ( 'type' ) ;
var text = $ ( this ) . children ( 'p' ) . text ( ) ;
$ ( this ) . data ( 'text' , text ) ;
$ ( this ) . children ( 'p' ) . remove ( ) ;
2013-10-22 20:11:03 +04:00
// add input field
2013-11-28 13:17:01 +04:00
var form = $ ( '<form></form>' ) ;
var input = $ ( '<input type="text">' ) ;
var newName = $ ( this ) . attr ( 'data-newname' ) || '' ;
if ( newName ) {
input . val ( newName ) ;
}
2013-08-16 02:31:27 +04:00
form . append ( input ) ;
$ ( this ) . append ( form ) ;
2013-11-28 13:17:01 +04:00
var lastPos ;
2013-10-22 20:11:03 +04:00
var checkInput = function ( ) {
var filename = input . val ( ) ;
if ( type === 'web' && filename . length === 0 ) {
2013-10-23 13:08:30 +04:00
throw t ( 'files' , 'URL cannot be empty' ) ;
2013-10-22 20:11:03 +04:00
} else if ( type !== 'web' && ! Files . isFileNameValid ( filename ) ) {
// Files.isFileNameValid(filename) throws an exception itself
} else if ( $ ( '#dir' ) . val ( ) === '/' && filename === 'Shared' ) {
2013-10-23 13:08:30 +04:00
throw t ( 'files' , 'In the home folder \'Shared\' is a reserved filename' ) ;
2013-10-22 20:11:03 +04:00
} else if ( FileList . inList ( filename ) ) {
throw t ( 'files' , '{new_name} already exists' , { new _name : filename } ) ;
} else {
return true ;
}
} ;
// 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' ) ;
}
} ) ;
2013-08-16 02:31:27 +04:00
input . focus ( ) ;
2013-11-28 13:17:01 +04:00
// pre select name up to the extension
lastPos = newName . lastIndexOf ( '.' ) ;
if ( lastPos === - 1 ) {
lastPos = newName . length ;
}
input . selectRange ( 0 , lastPos ) ;
2013-10-22 20:11:03 +04:00
form . submit ( function ( event ) {
2013-08-16 02:31:27 +04:00
event . stopPropagation ( ) ;
event . preventDefault ( ) ;
2013-10-22 20:11:03 +04:00
try {
checkInput ( ) ;
var newname = input . val ( ) ;
if ( FileList . lastAction ) {
FileList . lastAction ( ) ;
}
var name = getUniqueName ( newname ) ;
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' ) ,
{ dir : $ ( '#dir' ) . val ( ) , filename : name } ,
function ( result ) {
if ( result . status === 'success' ) {
var date = new Date ( ) ;
// TODO: ideally addFile should be able to receive
// all attributes and set them automatically,
// and also auto-load the preview
var tr = FileList . addFile ( name , 0 , date , false , hidden ) ;
tr . attr ( 'data-size' , result . data . size ) ;
tr . attr ( 'data-mime' , result . data . mime ) ;
tr . attr ( 'data-id' , result . data . id ) ;
2013-10-28 14:22:34 +04:00
tr . attr ( 'data-etag' , result . data . etag ) ;
2013-10-22 20:11:03 +04:00
tr . find ( '.filesize' ) . text ( humanFileSize ( result . data . size ) ) ;
var path = getPathForPreview ( name ) ;
2013-10-28 14:22:34 +04:00
Files . lazyLoadPreview ( path , result . data . mime , function ( previewpath ) {
2013-10-22 20:11:03 +04:00
tr . find ( 'td.filename' ) . attr ( 'style' , 'background-image:url(' + previewpath + ')' ) ;
2013-10-28 14:22:34 +04:00
} , null , null , result . data . etag ) ;
2013-10-22 20:11:03 +04:00
FileActions . display ( tr . find ( 'td.filename' ) , true ) ;
} else {
OC . dialogs . alert ( result . data . message , t ( 'core' , 'Could not create file' ) ) ;
}
2013-08-16 02:31:27 +04:00
}
2013-10-22 20:11:03 +04:00
) ;
break ;
case 'folder' :
$ . post (
OC . filePath ( 'files' , 'ajax' , 'newfolder.php' ) ,
{ dir : $ ( '#dir' ) . val ( ) , foldername : name } ,
function ( result ) {
if ( result . status === 'success' ) {
var date = new Date ( ) ;
FileList . addDir ( name , 0 , date , hidden ) ;
var tr = $ ( 'tr[data-file="' + name + '"]' ) ;
tr . attr ( 'data-id' , result . data . id ) ;
} else {
OC . dialogs . alert ( result . data . message , t ( 'core' , 'Could not create folder' ) ) ;
}
2013-08-16 02:31:27 +04:00
}
2013-10-22 20:11:03 +04:00
) ;
break ;
case 'web' :
if ( name . substr ( 0 , 8 ) !== 'https://' && name . substr ( 0 , 7 ) !== 'http://' ) {
name = 'http://' + name ;
2013-08-12 14:33:22 +04:00
}
2013-10-22 20:11:03 +04:00
var localName = name ;
if ( localName . substr ( localName . length - 1 , 1 ) === '/' ) { //strip /
localName = localName . substr ( 0 , localName . length - 1 ) ;
}
if ( localName . indexOf ( '/' ) ) { //use last part of url
localName = localName . split ( '/' ) . pop ( ) ;
} else { //or the domain
localName = ( localName . match ( /:\/\/(.[^\/]+)/ ) [ 1 ] ) . replace ( 'www.' , '' ) ;
}
localName = getUniqueName ( localName ) ;
2013-08-16 02:31:27 +04:00
//IE < 10 does not fire the necessary events for the progress bar.
2013-10-22 20:11:03 +04:00
if ( $ ( 'html.lte9' ) . length === 0 ) {
$ ( '#uploadprogressbar' ) . progressbar ( { value : 0 } ) ;
$ ( '#uploadprogressbar' ) . fadeIn ( ) ;
2013-08-16 02:31:27 +04:00
}
2013-10-22 20:11:03 +04:00
var eventSource = new OC . EventSource ( OC . filePath ( 'files' , 'ajax' , 'newfile.php' ) , { dir : $ ( '#dir' ) . val ( ) , source : name , filename : localName } ) ;
eventSource . listen ( 'progress' , function ( progress ) {
//IE < 10 does not fire the necessary events for the progress bar.
if ( $ ( 'html.lte9' ) . length === 0 ) {
$ ( '#uploadprogressbar' ) . progressbar ( 'value' , progress ) ;
}
2013-08-16 02:31:27 +04:00
} ) ;
2013-10-22 20:11:03 +04:00
eventSource . listen ( 'success' , function ( data ) {
var mime = data . mime ;
var size = data . size ;
var id = data . id ;
$ ( '#uploadprogressbar' ) . fadeOut ( ) ;
var date = new Date ( ) ;
FileList . addFile ( localName , size , date , false , hidden ) ;
var tr = $ ( 'tr[data-file="' + localName + '"]' ) ;
tr . data ( 'mime' , mime ) . data ( 'id' , id ) ;
tr . attr ( 'data-id' , id ) ;
var path = $ ( '#dir' ) . val ( ) + '/' + localName ;
2013-10-28 14:22:34 +04:00
Files . lazyLoadPreview ( path , mime , function ( previewpath ) {
2013-10-22 20:11:03 +04:00
tr . find ( 'td.filename' ) . attr ( 'style' , 'background-image:url(' + previewpath + ')' ) ;
2013-10-28 14:22:34 +04:00
} , null , null , data . etag ) ;
2013-10-22 20:11:03 +04:00
FileActions . display ( tr . find ( 'td.filename' ) , true ) ;
} ) ;
eventSource . listen ( 'error' , function ( error ) {
$ ( '#uploadprogressbar' ) . fadeOut ( ) ;
alert ( error ) ;
} ) ;
break ;
}
var li = form . parent ( ) ;
form . remove ( ) ;
/* workaround for IE 9&10 click event trap, 2 lines: */
$ ( 'input' ) . first ( ) . focus ( ) ;
$ ( '#content' ) . focus ( ) ;
li . append ( '<p>' + li . data ( 'text' ) + '</p>' ) ;
$ ( '#new>a' ) . click ( ) ;
} catch ( error ) {
input . attr ( 'title' , error ) ;
input . tipsy ( { gravity : 'w' , trigger : 'manual' } ) ;
input . tipsy ( 'show' ) ;
input . addClass ( 'error' ) ;
2013-08-12 14:33:22 +04:00
}
2013-06-27 00:51:38 +04:00
} ) ;
} ) ;
2013-09-01 18:14:46 +04:00
window . file _upload _param = file _upload _param ;
2013-06-27 00:51:38 +04:00
} ) ;