Source of
js/Ext.ux.FileUploader.js:
// vim: ts=4:sw=4:nu:fdc=4:nospell
/**
* Ext.ux.FileUploader
*
* @author Ing. Jozef Sakáloš
* @version $Id: Ext.ux.FileUploader.js 302 2008-08-03 20:57:33Z jozo $
* @date 15. March 2008
*
* @license Ext.ux.FileUploader is licensed under the terms of
* the Open Source LGPL 3.0 license. Commercial use is permitted to the extent
* that the code/component(s) do NOT become part of another Open Source or Commercially
* licensed development library or toolkit without explicit permission.
*
* License details: http://www.gnu.org/licenses/lgpl.html
*/
/*global Ext */
/**
* @class Ext.ux.FileUploader
* @extends Ext.util.Observable
* @constructor
*/
Ext
.
ux
.
FileUploader
=
function
(
config
) {
Ext
.
apply
(
this
,
config
);
// call parent
Ext
.
ux
.
FileUploader
.
superclass
.
constructor
.
apply
(
this
,
arguments
);
// add events
// {{{
this
.
addEvents
(
/**
* @event beforeallstart
* Fires before an upload (of all files) is started. Return false to cancel the event.
* @param {Ext.ux.FileUploader} this
*/
'beforeallstart'
/**
* @event allfinished
* Fires after upload (of all files) is finished
* @param {Ext.ux.FileUploader} this
*/
,
'allfinished'
/**
* @event beforefilestart
* Fires before the file upload is started. Return false to cancel the event.
* Fires only when singleUpload = false
* @param {Ext.ux.FileUploader} this
* @param {Ext.data.Record} record upload of which is being started
*/
,
'beforefilestart'
/**
* @event filefinished
* Fires when file finished uploading.
* Fires only when singleUpload = false
* @param {Ext.ux.FileUploader} this
* @param {Ext.data.Record} record upload of which has finished
*/
,
'filefinished'
/**
* @event progress
* Fires when progress has been updated
* @param {Ext.ux.FileUploader} this
* @param {Object} data Progress data object
* @param {Ext.data.Record} record Only if singleUpload = false
*/
,
'progress'
);
// }}}
};
// eo constructor
Ext
.
extend
(
Ext
.
ux
.
FileUploader
,
Ext
.
util
.
Observable
, {
// configuration options
// {{{
/**
* @cfg {Object} baseParams baseParams are sent to server in each request.
*/
baseParams
:{
cmd
:
'upload'
,
dir
:
'.'
}
/**
* @cfg {Boolean} concurrent true to start all requests upon upload start, false to start
* the next request only if previous one has been completed (or failed). Applicable only if
* singleUpload = false
*/
,
concurrent
:
true
/**
* @cfg {Boolean} enableProgress true to enable querying server for progress information
*/
,
enableProgress
:
true
/**
* @cfg {String} jsonErrorText Text to use for json error
*/
,
jsonErrorText
:
'Cannot decode JSON object'
/**
* @cfg {Number} Maximum client file size in bytes
*/
,
maxFileSize
:
524288
/**
* @cfg {String} progressIdName Name to give hidden field for upload progress identificator
*/
,
progressIdName
:
'UPLOAD_IDENTIFIER'
/**
* @cfg {Number} progressInterval How often (in ms) is progress requested from server
*/
,
progressInterval
:
2000
/**
* @cfg {String} progressUrl URL to request upload progress from
*/
,
progressUrl
:
'progress.php'
/**
* @cfg {Object} progressMap Mapping of received progress fields to store progress fields
*/
,
progressMap
:{
bytes_total
:
'bytesTotal'
,
bytes_uploaded
:
'bytesUploaded'
,
est_sec
:
'estSec'
,
files_uploaded
:
'filesUploaded'
,
speed_average
:
'speedAverage'
,
speed_last
:
'speedLast'
,
time_last
:
'timeLast'
,
time_start
:
'timeStart'
}
/**
* @cfg {Boolean} singleUpload true to upload files in one form, false to upload one by one
*/
,
singleUpload
:
false
/**
* @cfg {Ext.data.Store} store Mandatory. Store that holds files to upload
*/
/**
* @cfg {String} unknownErrorText Text to use for unknow error
*/
,
unknownErrorText
:
'Unknown error'
/**
* @cfg {String} url Mandatory. URL to upload to
*/
// }}}
// private
// {{{
/**
* uploads in progress count
* @private
*/
,
upCount
:
0
// }}}
// methods
// {{{
/**
* creates form to use for upload.
* @private
* @return {Ext.Element} form
*/
,
createForm
:
function
(
record
) {
var
progressId
=
parseInt
(
Math
.
random
() *
1
e10
,
10
);
var
form
=
Ext
.
getBody
().
createChild
({
tag
:
'form'
,
action
:
this
.
url
,
method
:
'post'
,
cls
:
'x-hidden'
,
id
:
Ext
.
id
()
,
cn
:[{
tag
:
'input'
,
type
:
'hidden'
,
name
:
'APC_UPLOAD_PROGRESS'
,
value
:
progressId
},{
tag
:
'input'
,
type
:
'hidden'
,
name
:
this
.
progressIdName
,
value
:
progressId
},{
tag
:
'input'
,
type
:
'hidden'
,
name
:
'MAX_FILE_SIZE'
,
value
:
this
.
maxFileSize
}]
});
if
(
record
) {
record
.
set
(
'form'
,
form
);
record
.
set
(
'progressId'
,
progressId
);
}
else
{
this
.
progressId
=
progressId
;
}
return
form
;
}
// eo function createForm
// }}}
// {{{
,
deleteForm
:
function
(
form
,
record
) {
form
.
remove
();
if
(
record
) {
record
.
set
(
'form'
,
null
);
}
}
// eo function deleteForm
// }}}
// {{{
/**
* Fires event(s) on upload finish/error
* @private
*/
,
fireFinishEvents
:
function
(
options
) {
if
(
true
!==
this
.
eventsSuspended
&& !
this
.
singleUpload
) {
this
.
fireEvent
(
'filefinished'
,
this
,
options
&&
options
.
record
);
}
if
(
true
!==
this
.
eventsSuspended
&&
0
===
this
.
upCount
) {
this
.
stopProgress
();
this
.
fireEvent
(
'allfinished'
,
this
);
}
}
// eo function fireFinishEvents
// }}}
// {{{
/**
* Geg the iframe identified by record
* @private
* @param {Ext.data.Record} record
* @return {Ext.Element} iframe or null if not found
*/
,
getIframe
:
function
(
record
) {
var
iframe
=
null
;
var
form
=
record
.
get
(
'form'
);
if
(
form
&&
form
.
dom
&&
form
.
dom
.
target
) {
iframe
=
Ext
.
get
(
form
.
dom
.
target
);
}
return
iframe
;
}
// eo function getIframe
// }}}
// {{{
/**
* returns options for Ajax upload request
* @private
* @param {Ext.data.Record} record
* @param {Object} params params to add
*/
,
getOptions
:
function
(
record
,
params
) {
var
o
= {
url
:
this
.
url
,
method
:
'post'
,
isUpload
:
true
,
scope
:
this
,
callback
:
this
.
uploadCallback
,
record
:
record
,
params
:
this
.
getParams
(
record
,
params
)
};
return
o
;
}
// eo function getOptions
// }}}
// {{{
/**
* get params to use for request
* @private
* @return {Object} params
*/
,
getParams
:
function
(
record
,
params
) {
var
p
= {
path
:
this
.
path
};
Ext
.
apply
(
p
,
this
.
baseParams
|| {},
params
|| {});
return
p
;
}
// }}}
// {{{
/**
* processes success response
* @private
* @param {Object} options options the request was called with
* @param {Object} response request response object
* @param {Object} o decoded response.responseText
*/
,
processSuccess
:
function
(
options
,
response
,
o
) {
var
record
=
false
;
// all files uploadded ok
if
(
this
.
singleUpload
) {
this
.
store
.
each
(
function
(
r
) {
r
.
set
(
'state'
,
'done'
);
r
.
set
(
'error'
,
''
);
r
.
commit
();
});
}
else
{
record
=
options
.
record
;
record
.
set
(
'state'
,
'done'
);
record
.
set
(
'error'
,
''
);
record
.
commit
();
}
this
.
deleteForm
(
options
.
form
,
record
);
}
// eo processSuccess
// }}}
// {{{
/**
* processes failure response
* @private
* @param {Object} options options the request was called with
* @param {Object} response request response object
* @param {String/Object} error Error text or JSON decoded object. Optional.
*/
,
processFailure
:
function
(
options
,
response
,
error
) {
var
record
=
options
.
record
;
var
records
;
// singleUpload - all files uploaded in one form
if
(
this
.
singleUpload
) {
// some files may have been successful
records
=
this
.
store
.
queryBy
(
function
(
r
){
var
state
=
r
.
get
(
'state'
);
return
'done'
!==
state
&&
'uploading'
!==
state
;
});
records
.
each
(
function
(
record
) {
var
e
=
error
.
errors ? error
.
errors
[
record
.
id
] :
this
.
unknownErrorText
;
if
(
e
) {
record
.
set
(
'state'
,
'failed'
);
record
.
set
(
'error'
,
e
);
Ext
.
getBody
().
appendChild
(
record
.
get
(
'input'
));
}
else
{
record
.
set
(
'state'
,
'done'
);
record
.
set
(
'error'
,
''
);
}
record
.
commit
();
},
this
);
this
.
deleteForm
(
options
.
form
);
}
// multipleUpload - each file uploaded in it's own form
else
{
if
(
error
&&
'object'
===
Ext
.
type
(
error
)) {
record
.
set
(
'error'
,
error
.
errors
&&
error
.
errors
[
record
.
id
]
? error
.
errors
[
record
.
id
] :
this
.
unknownErrorText
);
}
else if
(
error
) {
record
.
set
(
'error'
,
error
);
}
else if
(
response
&&
response
.
responseText
) {
record
.
set
(
'error'
,
response
.
responseText
);
}
else
{
record
.
set
(
'error'
,
this
.
unknownErrorText
);
}
record
.
set
(
'state'
,
'failed'
);
record
.
commit
();
}
}
// eof processFailure
// }}}
// {{{
/**
* Delayed task callback
*/
,
requestProgress
:
function
() {
var
records
,
p
;
var
o
= {
url
:
this
.
progressUrl
,
method
:
'post'
,
params
:{}
,
scope
:
this
,
callback
:
function
(
options
,
success
,
response
) {
var
o
;
if
(
true
!==
success
) {
return
;
}
try
{
o
=
Ext
.
decode
(
response
.
responseText
);
}
catch
(
e
) {
return
;
}
if
(
'object'
!==
Ext
.
type
(
o
) ||
true
!==
o
.
success
) {
return
;
}
if
(
this
.
singleUpload
) {
this
.
progress
= {};
for
(
p
in
o
) {
if
(
this
.
progressMap
[
p
]) {
this
.
progress
[
this
.
progressMap
[
p
]] =
parseInt
(
o
[
p
],
10
);
}
}
if
(
true
!==
this
.
eventsSuspended
) {
this
.
fireEvent
(
'progress'
,
this
,
this
.
progress
);
}
}
else
{
for
(
p
in
o
) {
if
(
this
.
progressMap
[
p
] &&
options
.
record
) {
options
.
record
.
set
(
this
.
progressMap
[
p
],
parseInt
(
o
[
p
],
10
));
}
}
if
(
options
.
record
) {
options
.
record
.
commit
();
if
(
true
!==
this
.
eventsSuspended
) {
this
.
fireEvent
(
'progress'
,
this
,
options
.
record
.
data
,
options
.
record
);
}
}
}
this
.
progressTask
.
delay
(
this
.
progressInterval
);
}
};
if
(
this
.
singleUpload
) {
o
.
params
[
this
.
progressIdName
] =
this
.
progressId
;
o
.
params
.
APC_UPLOAD_PROGRESS
=
this
.
progressId
;
Ext
.
Ajax
.
request
(
o
);
}
else
{
records
=
this
.
store
.
query
(
'state'
,
'uploading'
);
records
.
each
(
function
(
r
) {
o
.
params
[
this
.
progressIdName
] =
r
.
get
(
'progressId'
);
o
.
params
.
APC_UPLOAD_PROGRESS
=
o
.
params
[
this
.
progressIdName
];
o
.
record
=
r
;
(
function
() {
Ext
.
Ajax
.
request
(
o
);
}).
defer
(
250
);
},
this
);
}
}
// eo function requestProgress
// }}}
// {{{
/**
* path setter
* @private
*/
,
setPath
:
function
(
path
) {
this
.
path
=
path
;
}
// eo setPath
// }}}
// {{{
/**
* url setter
* @private
*/
,
setUrl
:
function
(
url
) {
this
.
url
=
url
;
}
// eo setUrl
// }}}
// {{{
/**
* Starts progress fetching from server
* @private
*/
,
startProgress
:
function
() {
if
(!
this
.
progressTask
) {
this
.
progressTask
=
new
Ext
.
util
.
DelayedTask
(
this
.
requestProgress
,
this
);
}
this
.
progressTask
.
delay
.
defer
(
this
.
progressInterval
/
2
,
this
.
progressTask
, [
this
.
progressInterval
]);
}
// eo function startProgress
// }}}
// {{{
/**
* Stops progress fetching from server
* @private
*/
,
stopProgress
:
function
() {
if
(
this
.
progressTask
) {
this
.
progressTask
.
cancel
();
}
}
// eo function stopProgress
// }}}
// {{{
/**
* Stops all currently running uploads
*/
,
stopAll
:
function
() {
var
records
=
this
.
store
.
query
(
'state'
,
'uploading'
);
records
.
each
(
this
.
stopUpload
,
this
);
}
// eo function stopAll
// }}}
// {{{
/**
* Stops currently running upload
* @param {Ext.data.Record} record Optional, if not set singleUpload = true is assumed
* and the global stop is initiated
*/
,
stopUpload
:
function
(
record
) {
// single abord
var
iframe
=
false
;
if
(
record
) {
iframe
=
this
.
getIframe
(
record
);
this
.
stopIframe
(
iframe
);
this
.
upCount
--;
this
.
upCount
=
0
>
this
.
upCount ?
0
:
this
.
upCount
;
record
.
set
(
'state'
,
'stopped'
);
this
.
fireFinishEvents
({
record
:
record
});
}
// all abort
else if
(
this
.
form
) {
iframe
=
Ext
.
fly
(
this
.
form
.
dom
.
target
);
this
.
stopIframe
(
iframe
);
this
.
upCount
=
0
;
this
.
fireFinishEvents
();
}
}
// eo function abortUpload
// }}}
// {{{
/**
* Stops uploading in hidden iframe
* @private
* @param {Ext.Element} iframe
*/
,
stopIframe
:
function
(
iframe
) {
if
(
iframe
) {
try
{
iframe
.
dom
.
contentWindow
.
stop
();
iframe
.
remove
.
defer
(
250
,
iframe
);
}
catch
(
e
){}
}
}
// eo function stopIframe
// }}}
// {{{
/**
* Main public interface function. Preforms the upload
*/
,
upload
:
function
() {
var
records
=
this
.
store
.
queryBy
(
function
(
r
){
return
'done'
!==
r
.
get
(
'state'
);});
if
(!
records
.
getCount
()) {
return
;
}
// fire beforeallstart event
if
(
true
!==
this
.
eventsSuspended
&&
false
===
this
.
fireEvent
(
'beforeallstart'
,
this
)) {
return
;
}
if
(
this
.
singleUpload
) {
this
.
uploadSingle
();
}
else
{
records
.
each
(
this
.
uploadFile
,
this
);
}
if
(
true
===
this
.
enableProgress
) {
this
.
startProgress
();
}
}
// eo function upload
// }}}
// {{{
/**
* called for both success and failure. Does nearly nothing
* @private
* but dispatches processing to processSuccess and processFailure functions
*/
,
uploadCallback
:
function
(
options
,
success
,
response
) {
var
o
;
this
.
upCount
--;
this
.
form
=
false
;
// process ajax success
if
(
true
===
success
) {
try
{
o
=
Ext
.
decode
(
response
.
responseText
);
}
catch
(
e
) {
this
.
processFailure
(
options
,
response
,
this
.
jsonErrorText
);
this
.
fireFinishEvents
(
options
);
return
;
}
// process command success
if
(
true
===
o
.
success
) {
this
.
processSuccess
(
options
,
response
,
o
);
}
// process command failure
else
{
this
.
processFailure
(
options
,
response
,
o
);
}
}
// process ajax failure
else
{
this
.
processFailure
(
options
,
response
);
}
this
.
fireFinishEvents
(
options
);
}
// eo function uploadCallback
// }}}
// {{{
/**
* Uploads one file
* @param {Ext.data.Record} record
* @param {Object} params Optional. Additional params to use in request.
*/
,
uploadFile
:
function
(
record
,
params
) {
// fire beforestart event
if
(
true
!==
this
.
eventsSuspended
&&
false
===
this
.
fireEvent
(
'beforefilestart'
,
this
,
record
)) {
return
;
}
// create form for upload
var
form
=
this
.
createForm
(
record
);
// append input to the form
var
inp
=
record
.
get
(
'input'
);
inp
.
set
({
name
:
inp
.
id
});
form
.
appendChild
(
inp
);
// get params for request
var
o
=
this
.
getOptions
(
record
,
params
);
o
.
form
=
form
;
// set state
record
.
set
(
'state'
,
'uploading'
);
record
.
set
(
'pctComplete'
,
0
);
// increment active uploads count
this
.
upCount
++;
// request upload
Ext
.
Ajax
.
request
(
o
);
// todo:delete after devel
this
.
getIframe
.
defer
(
100
,
this
, [
record
]);
}
// eo function uploadFile
// }}}
// {{{
/**
* Uploads all files in single request
*/
,
uploadSingle
:
function
() {
// get records to upload
var
records
=
this
.
store
.
queryBy
(
function
(
r
){
return
'done'
!==
r
.
get
(
'state'
);});
if
(!
records
.
getCount
()) {
return
;
}
// create form and append inputs to it
var
form
=
this
.
createForm
();
records
.
each
(
function
(
record
) {
var
inp
=
record
.
get
(
'input'
);
inp
.
set
({
name
:
inp
.
id
});
form
.
appendChild
(
inp
);
record
.
set
(
'state'
,
'uploading'
);
},
this
);
// create options for request
var
o
=
this
.
getOptions
();
o
.
form
=
form
;
// save form for stop
this
.
form
=
form
;
// increment active uploads counter
this
.
upCount
++;
// request upload
Ext
.
Ajax
.
request
(
o
);
}
// eo function uploadSingle
// }}}
});
// eo extend
// register xtype
Ext
.
reg
(
'fileuploader'
,
Ext
.
ux
.
FileUploader
);
// eof
Free web analytics, website statistics