Files
server/usr/share/psa-horde/js/plupload/uploader.js
2026-01-07 20:52:11 +01:00

280 lines
12 KiB
JavaScript

/**
* File upload widget based on puploader.
* See: http://www.plupload.com
*
* Uses the pluploader lower level API to sort-of duplicate the idea behind the
* jquery widget.
*
* Requires: puploader.js (v1.5.1+) as well as the runtime files for the desired
* runtimes, e.g. puploader.html5.js.
*
* Usage:
* ======
* var uploader = new Horde_Uploader({
* 'container' - (string) Dom id of the parent container to place the
* widget it.
* 'target' - (string) Url of target page
* 'drop_target' (string) Dom id of element to hold file list
* 'swf_path' - (string) (optional) Path to flash file
* 'xap_path' - (string) (optional) Path to silverlight file
* 'browsebutton_class' |
* 'uploadbutton_class' | - CSS class names for various elements.
* 'filelist_class' |
* 'browse_button' dom id to use for the file browser button.
* 'upload_button' dom id to use for the upload start butotn.
* 'text' - hash of various strings used in the interface.,
* 'return_target'
* });
*
* @author Michael J. Rubinsky <mrubinsk@horde.org>
*/
var Horde_Uploader = Class.create({
// Holds files selected by user while they are in the process of being
// added to the queue.
_queue: [],
// Default event handlers.
handlers: {
filesadded: function(up, files)
{
this._queue = files;
$(this._params['upload_button']).show();
},
/**
* TODO: tweak the selector usage... implement a progress bar.
*/
progress: function(up, file)
{
// Refresh the uploader when done. Might be a better way to do this
// but the documentation is pretty lacking.
if (up.total.percent == 100) {
up.files = [];
up.refresh();
$(this._params['return_button']).show();
}
$(file.id).select('.hordeUploaderFilestatus').each(function(p) { p.update(file.percent + '%') });
},
/**
*
*/
init: function(up, params)
{
},
/**
* Receives the server response in response and is responsible for
* updating the UI accordingly
*/
fileuploaded: function(up, file, response) {
try {
var result = response.response.evalJSON();
if (result.status != 200) {
up.unbind('UploadProgress', this.handlers.progress);
$(file.id).select('.hordeUploaderFilestatus').each(function(p) { $(p).update(result.error.message); });
$(file.id).addClassName(this._params['filelistitemerror_class']);
$(file.id).select('.hordeUploaderFileaction').each(function(p) {
$(p).select('.hordeUploaderRemove').each(function(r) { r.remove(); });
$(p).addClassName(this._params['error_class']) }.bind(this));
} else {
$(file.id).addClassName(this._params['filelistitemdone_class']);
$(file.id).select('.hordeUploaderFileaction').each(function(p) {
$(p).select('.hordeUploaderRemove').each(function(r) { r.remove(); });
$(p).update('&nbsp;').addClassName(this._params['success_class']);
}.bind(this));
}
} catch (Exception) {
up.unbind('UploadProgress', this.handlers.progress);
$(file.id).select('.hordeUploaderFileaction').each(function(p) {
$(p).select('.hordeUploaderRemove').each(function(r) { r.remove(); });
$(p).update('&nbsp;').addClassName(this._params['error_class']);
}.bind(this));
$(file.id).select('.hordeUploaderFilestatus').each(function(p) { $(p).update(Exception); });
}
},
error: function(up, err) {
var file = err.file, message;
if (file) {
message = err.message;
if (err.details) {
message += ' (' + err.details + ')';
}
if (err.code == plupload.FILE_SIZE_ERROR) {
alert(this._params.text.size + ' ' + file.name);
}
if (err.code == plupload.FILE_EXTENSION_ERROR) {
alert(this._params.text.type + ' ' + file.name);
}
}
},
queuechanged: function(up) {
this.updateList();
},
uploadcomplete: function(up, files) {
$(this._params['upload_button']).hide();
},
// Handlers that may be useful for client code. Not used by default.
// Override before creating object if needed.
uploadfile: function(up, file) {},
statechanged: function(up) {},
filesremoved: function(up, files) {},
chunkuploaded: function(up, file, response) {}
},
/**
* Params required: container, target.
* Params not required, but have no defaults: swf_path, xap_path
* Parms with sensible defaults: browsebutton_class, uploadbutton_class,
* filelist_class, browse_button, drop_target,
* upload_button, upload_button
*/
initialize: function(params, handlers)
{
this._params = Object.extend({
browsebutton_class: 'horde-button',
uploadbutton_class: 'horde-button',
header_class: 'hordeUploaderHeader',
headercontent_class: 'hordeUploaderHeaderContent',
subheader_class: 'hordeUploaderSubHeader',
container_class: 'hordeUploaderContainer',
filelist_class: 'hordeUploaderFilelist',
filelistitem_class: 'hordeUploaderFilelistItem',
filelistitemdone_class: 'hordeUploaderFilelistItemDone',
filelistitemerror_class: 'hordeUploaderFilelistItemError',
browse_button: 'browseimages',
drop_target: 'filelist',
upload_button: 'uploadimages',
return_button: 'return',
returnbutton_class: 'horde-button',
success_class: 'hordeUploaderSuccess',
error_class: 'hordeUploaderError',
footer_class: 'hordeUploaderFooter',
multipart: false,
max_file_size: false,
chunk_size: false
}, params);
this.handlers = Object.extend(this.handlers, handlers);
this._build();
var opts = {
runtimes: 'html5, flash, silverlight, browserplus',
browse_button: this._params['browse_button'],
url: this._params['target'],
drop_element: this._params['drop_target'],
flash_swf_url: this._params['swf_path'],
silverlight_xap_url: this._params['xap_path'],
multipart: this._params['multipart']
};
if (this._params['max_file_size']) {
opts.max_file_size = this._params['max_file_size'];
}
if (this._params['chunk_size']) {
opts.chunk_size = this._params['chunk_size'];
}
this._puploader = new plupload.Uploader(opts);
this._puploader.bind('UploadProgress', this.handlers.progress, this);
this._puploader.bind('Init', this.handlers.init, this);
this._puploader.bind('FilesAdded', this.handlers.filesadded, this);
this._puploader.bind('UploadFile', this.handlers.uploadfile, this);
this._puploader.bind('FileUploaded', this.handlers.fileuploaded, this);
this._puploader.bind('Error', this.handlers.error, this);
this._puploader.bind('StateChanged', this.handlers.statechanged, this);
this._puploader.bind('QueueChanged', this.handlers.queuechanged, this);
this._puploader.bind('FilesRemoved', this.handlers.filesremoved, this);
this._puploader.bind('ChunkUploaded', this.handlers.chunkuploaded, this);
this._puploader.bind('UploadComplete', this.handlers.uploadcomplete, this);
},
init: function()
{
this._puploader.init();
$(this._params['upload_button']).observe('click', function(e) {
this._puploader.start();
e.stop();
}.bindAsEventListener(this));
this.setReturnTarget(this._params['return_target']);
$(this._params['return_button']).hide();
$(this._params['upload_button']).hide();
},
setReturnTarget: function(path)
{
$(this._params['return_button']).observe('click', function() { window.location = path });
},
updateList: function()
{
$(this._params['return_button']).hide();
this._queue.each(function(file) {
var f = file;
if (f.status == plupload.QUEUED) {
var remove = new Element('div', {'class': 'hordeUploaderRemove'}).update('&nbsp;');
var newdiv = new Element('li',
{ 'class': this._params.filelistitem_class,
'id': f.id
})
.insert(new Element('div', { 'class': 'hordeUploaderFilename' }).update(f.name))
.insert(new Element('div', { 'class': 'hordeUploaderFileaction' }).update(remove))
.insert(new Element('div', { 'class': 'hordeUploaderFilestatus' }).update('&nbsp'))
.insert(new Element('div', { 'class': 'hordeUploaderFilesize' }).update(plupload.formatSize(f.size)));
remove.observe('click', function(e) { var f = this._puploader.getFile(newdiv.id); this._puploader.removeFile(f); $(newdiv.id).remove(); }.bind(this));
$(this._params['drop_target']).select('.hordeUploaderFileUl').each(function(p) { p.insert(newdiv) });
}
}.bind(this));
this._queue = [];
},
/**
* Draw the upload widget.
*/
_build: function()
{
/* Filelist, with embedded UL */
var filelist = new Element('div',
{ 'id': this._params['drop_target'],
'class': this._params['filelist_class'] }).insert(new Element('ul', { 'class': 'hordeUploaderFileUl' }));
/* Browse button */
var browse = new Element('input', { 'id': this._params['browse_button'], 'type': 'button', 'class': this._params['browsebutton_class'], 'value': this._params.text.add });
/* Upload button */
var upload = new Element('input', { 'id': this._params['upload_button'], 'type': 'button', 'class': this._params['uploadbutton_class'], 'value': this._params.text.start });
/* Return button (Activated when uploader is DONE). */
var returnButton = new Element('input', { 'id': this._params['return_button'], 'type': 'button', 'class': this._params['returnbutton_class'], 'value': this._params.text.returnButton });
/* Header section */
var subheader = new Element('div', { 'class': this._params['subheader_class'] }).update(this._params.text.subheader);
var headercontent = new Element('div', { 'class': this._params['headercontent_class'] }).update(this._params.text.header);
headercontent.insert(subheader);
var header = new Element('div', { 'class': this._params['header_class'] }).update(headercontent);
/* Footer */
var footer = new Element('div', { 'class': this._params['footer_class'] });
/* filelist header rows */
var fileheader = new Element('div', { 'class': 'hordeUploaderFilelistHeader'})
.insert(new Element('div', { 'class': 'hordeUploaderFilename' }).update('Filename'))
.insert(new Element('div', { 'class': 'hordeUploaderFileaction'}).update('&nbsp;'))
.insert(new Element('div', { 'class': 'hordeUploaderFilestatus'}).update('Status'))
.insert(new Element('div', { 'class': 'hordeUploaderFilesize' }).update('Size'));
/* Build full widget, Insert into the DOM */
$(this._params['container']).insert(
new Element('div', {'class': this._params['container_class'] })
.insert(header)
.insert(fileheader)
.insert(new Element('div', { 'class': 'clear' }))
.insert(filelist)
.insert(footer.insert(browse).insert(upload).insert(returnButton))
);
}
});