1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324 |
- /**
- * jquery.ui.plupload.js
- *
- * Copyright 2013, Moxiecode Systems AB
- * Released under GPL License.
- *
- * License: http://www.plupload.com/license
- * Contributing: http://www.plupload.com/contributing
- *
- * Depends:
- * jquery.ui.core.js
- * jquery.ui.widget.js
- * jquery.ui.button.js
- * jquery.ui.progressbar.js
- *
- * Optionally:
- * jquery.ui.sortable.js
- */
- /* global jQuery:true */
- /**
- jQuery UI based implementation of the Plupload API - multi-runtime file uploading API.
- To use the widget you must include _jQuery_ and _jQuery UI_ bundle (including `ui.core`, `ui.widget`, `ui.button`,
- `ui.progressbar` and `ui.sortable`).
- In general the widget is designed the way that you do not usually need to do anything to it after you instantiate it.
- But! You still can intervenue, to some extent, in case you need to. Although, due to the fact that widget is based on
- _jQuery UI_ widget factory, there are some specifics. See examples below for more details.
- @example
- <!-- Instantiating: -->
- <div id="uploader">
- <p>Your browser doesn't have Flash, Silverlight or HTML5 support.</p>
- </div>
- <script>
- $('#uploader').plupload({
- url : '../upload.php',
- filters : [
- {title : "Image files", extensions : "jpg,gif,png"}
- ],
- rename: true,
- sortable: true,
- flash_swf_url : '../../js/Moxie.swf',
- silverlight_xap_url : '../../js/Moxie.xap',
- });
- </script>
- @example
- // Invoking methods:
- $('#uploader').plupload(options);
- // Display welcome message in the notification area
- $('#uploader').plupload('notify', 'info', "This might be obvious, but you need to click 'Add Files' to add some files.");
- @example
- // Subscribing to the events...
- // ... on initialization:
- $('#uploader').plupload({
- ...
- viewchanged: function(event, args) {
- // stuff ...
- }
- });
- // ... or after initialization
- $('#uploader').on("viewchanged", function(event, args) {
- // stuff ...
- });
- @class UI.Plupload
- @constructor
- @param {Object} settings For detailed information about each option check documentation.
- @param {String} settings.url URL of the server-side upload handler.
- @param {Number|String} [settings.chunk_size=0] Chunk size in bytes to slice the file into. Shorcuts with b, kb, mb, gb, tb suffixes also supported. `e.g. 204800 or "204800b" or "200kb"`. By default - disabled.
- @param {String} [settings.file_data_name="file"] Name for the file field in Multipart formated message.
- @param {Object} [settings.filters={}] Set of file type filters.
- @param {Array} [settings.filters.mime_types=[]] List of file types to accept, each one defined by title and list of extensions. `e.g. {title : "Image files", extensions : "jpg,jpeg,gif,png"}`. Dispatches `plupload.FILE_EXTENSION_ERROR`
- @param {String|Number} [settings.filters.max_file_size=0] Maximum file size that the user can pick, in bytes. Optionally supports b, kb, mb, gb, tb suffixes. `e.g. "10mb" or "1gb"`. By default - not set. Dispatches `plupload.FILE_SIZE_ERROR`.
- @param {Boolean} [settings.filters.prevent_duplicates=false] Do not let duplicates into the queue. Dispatches `plupload.FILE_DUPLICATE_ERROR`.
- @param {Number} [settings.filters.max_file_count=0] Limit the number of files that can reside in the queue at the same time (default is 0 - no limit).
- @param {String} [settings.flash_swf_url] URL of the Flash swf.
- @param {Object} [settings.headers] Custom headers to send with the upload. Hash of name/value pairs.
- @param {Number|String} [settings.max_file_size] Maximum file size that the user can pick, in bytes. Optionally supports b, kb, mb, gb, tb suffixes. `e.g. "10mb" or "1gb"`. By default - not set. Dispatches `plupload.FILE_SIZE_ERROR`.
- @param {Number} [settings.max_retries=0] How many times to retry the chunk or file, before triggering Error event.
- @param {Boolean} [settings.multipart=true] Whether to send file and additional parameters as Multipart formated message.
- @param {Object} [settings.multipart_params] Hash of key/value pairs to send with every file upload.
- @param {Boolean} [settings.multi_selection=true] Enable ability to select multiple files at once in file dialog.
- @param {Boolean} [settings.prevent_duplicates=false] Do not let duplicates into the queue. Dispatches `plupload.FILE_DUPLICATE_ERROR`.
- @param {String|Object} [settings.required_features] Either comma-separated list or hash of required features that chosen runtime should absolutely possess.
- @param {Object} [settings.resize] Enable resizng of images on client-side. Applies to `image/jpeg` and `image/png` only. `e.g. {width : 200, height : 200, quality : 90, crop: true}`
- @param {Number} [settings.resize.width] If image is bigger, it will be resized.
- @param {Number} [settings.resize.height] If image is bigger, it will be resized.
- @param {Number} [settings.resize.quality=90] Compression quality for jpegs (1-100).
- @param {Boolean} [settings.resize.crop=false] Whether to crop images to exact dimensions. By default they will be resized proportionally.
- @param {String} [settings.runtimes="html5,flash,silverlight,html4"] Comma separated list of runtimes, that Plupload will try in turn, moving to the next if previous fails.
- @param {String} [settings.silverlight_xap_url] URL of the Silverlight xap.
- @param {Boolean} [settings.unique_names=false] If true will generate unique filenames for uploaded files.
- @param {Boolean} [settings.autostart=false] Whether to auto start uploading right after file selection.
- @param {Boolean} [settings.dragdrop=true] Enable ability to add file to the queue by drag'n'dropping them from the desktop.
- @param {Boolean} [settings.rename=false] Enable ability to rename files in the queue.
- @param {Boolean} [settings.sortable=false] Enable ability to sort files in the queue, changing their uploading priority.
- @param {Object} [settings.buttons] Control the visibility of functional buttons.
- @param {Boolean} [settings.buttons.browse=true] Display browse button.
- @param {Boolean} [settings.buttons.start=true] Display start button.
- @param {Boolean} [settings.buttons.stop=true] Display stop button.
- @param {Object} [settings.views] Control various views of the file queue.
- @param {Boolean} [settings.views.list=true] Enable list view.
- @param {Boolean} [settings.views.thumbs=false] Enable thumbs view.
- @param {String} [settings.views.default='list'] Default view.
- @param {Boolean} [settings.views.remember=true] Whether to remember the current view (requires jQuery Cookie plugin).
- @param {Boolean} [settings.multiple_queues=true] Re-activate the widget after each upload procedure.
- */
- ;(function(window, document, plupload, o, $) {
- /**
- Dispatched when the widget is initialized and ready.
- @event ready
- @param {plupload.Uploader} uploader Uploader instance sending the event.
- */
- /**
- Dispatched when file dialog is closed.
- @event selected
- @param {plupload.Uploader} uploader Uploader instance sending the event.
- @param {Array} files Array of selected files represented by plupload.File objects
- */
- /**
- Dispatched when file dialog is closed.
- @event removed
- @param {plupload.Uploader} uploader Uploader instance sending the event.
- @param {Array} files Array of removed files represented by plupload.File objects
- */
- /**
- Dispatched when upload is started.
- @event start
- @param {plupload.Uploader} uploader Uploader instance sending the event.
- */
- /**
- Dispatched when upload is stopped.
- @event stop
- @param {plupload.Uploader} uploader Uploader instance sending the event.
- */
- /**
- Dispatched during the upload process.
- @event progress
- @param {plupload.Uploader} uploader Uploader instance sending the event.
- @param {plupload.File} file File that is being uploaded (includes loaded and percent properties among others).
- @param {Number} size Total file size in bytes.
- @param {Number} loaded Number of bytes uploaded of the files total size.
- @param {Number} percent Number of percentage uploaded of the file.
- */
- /**
- Dispatched when file is uploaded.
- @event uploaded
- @param {plupload.Uploader} uploader Uploader instance sending the event.
- @param {plupload.File} file File that was uploaded.
- @param {Enum} status Status constant matching the plupload states QUEUED, UPLOADING, FAILED, DONE.
- */
- /**
- Dispatched when upload of the whole queue is complete.
- @event complete
- @param {plupload.Uploader} uploader Uploader instance sending the event.
- @param {Array} files Array of uploaded files represented by plupload.File objects
- */
- /**
- Dispatched when the view is changed, e.g. from `list` to `thumbs` or vice versa.
- @event viewchanged
- @param {plupload.Uploader} uploader Uploader instance sending the event.
- @param {String} type Current view type.
- */
- /**
- Dispatched when error of some kind is detected.
- @event error
- @param {plupload.Uploader} uploader Uploader instance sending the event.
- @param {String} error Error message.
- @param {plupload.File} file File that was uploaded.
- @param {Enum} status Status constant matching the plupload states QUEUED, UPLOADING, FAILED, DONE.
- */
- var uploaders = {};
-
- function _(str) {
- return plupload.translate(str) || str;
- }
- function renderUI(obj) {
- obj.id = obj.attr('id');
- obj.html(
- '<div class="plupload_wrapper">' +
- '<div class="ui-widget-content plupload_container">' +
- '<div class="ui-state-default ui-widget-header plupload_header">' +
- '<div class="plupload_header_content">' +
- '<div class="plupload_logo"> </div>' +
- '<div class="plupload_header_title">' + _("Select files") + '</div>' +
- '<div class="plupload_header_text">' + _("Add files to the upload queue and click the start button.") + '</div>' +
- '<div class="plupload_view_switch">' +
- '<input type="radio" id="'+obj.id+'_view_list" name="view_mode_'+obj.id+'" checked="checked" /><label class="plupload_button" for="'+obj.id+'_view_list" data-view="list">' + _('List') + '</label>' +
- '<input type="radio" id="'+obj.id+'_view_thumbs" name="view_mode_'+obj.id+'" /><label class="plupload_button" for="'+obj.id+'_view_thumbs" data-view="thumbs">' + _('Thumbnails') + '</label>' +
- '</div>' +
- '</div>' +
- '</div>' +
- '<table class="plupload_filelist plupload_filelist_header ui-widget-header">' +
- '<tr>' +
- '<td class="plupload_cell plupload_file_name">' + _('Filename') + '</td>' +
- '<td class="plupload_cell plupload_file_status">' + _('Status') + '</td>' +
- '<td class="plupload_cell plupload_file_size">' + _('Size') + '</td>' +
- '<td class="plupload_cell plupload_file_action"> </td>' +
- '</tr>' +
- '</table>' +
- '<div class="plupload_content">' +
- '<div class="plupload_droptext">' + _("Drag files here.") + '</div>' +
- '<ul class="plupload_filelist_content"> </ul>' +
- '<div class="plupload_clearer"> </div>' +
- '</div>' +
-
- '<table class="plupload_filelist plupload_filelist_footer ui-widget-header">' +
- '<tr>' +
- '<td class="plupload_cell plupload_file_name">' +
- '<div class="plupload_buttons"><!-- Visible -->' +
- '<a class="plupload_button plupload_add">' + _("Add Files") + '</a> ' +
- '<a class="plupload_button plupload_start">' + _("Start Upload") + '</a> ' +
- '<a class="plupload_button plupload_stop plupload_hidden">'+_("Stop Upload") + '</a> ' +
- '</div>' +
- '<div class="plupload_started plupload_hidden"><!-- Hidden -->' +
- '<div class="plupload_progress plupload_right">' +
- '<div class="plupload_progress_container"></div>' +
- '</div>' +
- '<div class="plupload_cell plupload_upload_status"></div>' +
- '<div class="plupload_clearer"> </div>' +
- '</div>' +
- '</td>' +
- '<td class="plupload_file_status"><span class="plupload_total_status">0%</span></td>' +
- '<td class="plupload_file_size"><span class="plupload_total_file_size">0 kb</span></td>' +
- '<td class="plupload_file_action"></td>' +
- '</tr>' +
- '</table>' +
- '</div>' +
- '<input class="plupload_count" value="0" type="hidden">' +
- '</div>'
- );
- }
- $.widget("ui.plupload", {
- widgetEventPrefix: '',
-
- contents_bak: '',
-
- options: {
- browse_button_hover: 'ui-state-hover',
- browse_button_active: 'ui-state-active',
- filters: {},
-
- // widget specific
- buttons: {
- browse: true,
- start: true,
- stop: true
- },
-
- views: {
- list: true,
- thumbs: false,
- active: 'list',
- remember: true // requires: https://github.com/carhartl/jquery-cookie, otherwise disabled even if set to true
- },
- thumb_width: 100,
- thumb_height: 60,
- multiple_queues: true, // re-use widget by default
- dragdrop : true,
- autostart: false,
- sortable: false,
- rename: false
- },
-
- FILE_COUNT_ERROR: -9001,
-
- _create: function() {
- var id = this.element.attr('id');
- if (!id) {
- id = plupload.guid();
- this.element.attr('id', id);
- }
- this.id = id;
-
- // backup the elements initial state
- this.contents_bak = this.element.html();
- renderUI(this.element);
-
- // container, just in case
- this.container = $('.plupload_container', this.element).attr('id', id + '_container');
- this.content = $('.plupload_content', this.element);
-
- if ($.fn.resizable) {
- this.container.resizable({
- handles: 's',
- minHeight: 300
- });
- }
-
- // list of files, may become sortable
- this.filelist = $('.plupload_filelist_content', this.container)
- .attr({
- id: id + '_filelist',
- unselectable: 'on'
- });
-
- // buttons
- this.browse_button = $('.plupload_add', this.container).attr('id', id + '_browse');
- this.start_button = $('.plupload_start', this.container).attr('id', id + '_start');
- this.stop_button = $('.plupload_stop', this.container).attr('id', id + '_stop');
- this.thumbs_switcher = $('#' + id + '_view_thumbs');
- this.list_switcher = $('#' + id + '_view_list');
-
- if ($.ui.button) {
- this.browse_button.button({
- icons: { primary: 'ui-icon-circle-plus' },
- disabled: true
- });
-
- this.start_button.button({
- icons: { primary: 'ui-icon-circle-arrow-e' },
- disabled: true
- });
-
- this.stop_button.button({
- icons: { primary: 'ui-icon-circle-close' }
- });
-
- this.list_switcher.button({
- text: false,
- icons: { secondary: "ui-icon-grip-dotted-horizontal" }
- });
- this.thumbs_switcher.button({
- text: false,
- icons: { secondary: "ui-icon-image" }
- });
- }
-
- // progressbar
- this.progressbar = $('.plupload_progress_container', this.container);
-
- if ($.ui.progressbar) {
- this.progressbar.progressbar();
- }
-
- // counter
- this.counter = $('.plupload_count', this.element)
- .attr({
- id: id + '_count',
- name: id + '_count'
- });
-
- // initialize uploader instance
- this._initUploader();
- },
- _initUploader: function() {
- var self = this
- , id = this.id
- , uploader
- , options = {
- container: id + '_buttons',
- browse_button: id + '_browse'
- }
- ;
- $('.plupload_buttons', this.element).attr('id', id + '_buttons');
- if (self.options.dragdrop) {
- this.filelist.parent().attr('id', this.id + '_dropbox');
- options.drop_element = this.id + '_dropbox';
- }
- this.filelist.on('click', function(e) {
- if ($(e.target).hasClass('plupload_action_icon')) {
- self.removeFile($(e.target).closest('.plupload_file').attr('id'));
- e.preventDefault();
- }
- });
- uploader = this.uploader = uploaders[id] = new plupload.Uploader($.extend(this.options, options));
- if (self.options.views.thumbs) {
- uploader.settings.required_features.display_media = true;
- }
- // for backward compatibility
- if (self.options.max_file_count) {
- plupload.extend(uploader.getOption('filters'), {
- max_file_count: self.options.max_file_count
- });
- }
- plupload.addFileFilter('max_file_count', function(maxCount, file, cb) {
- if (maxCount <= this.files.length - (this.total.uploaded + this.total.failed)) {
- self.browse_button.button('disable');
- this.disableBrowse();
-
- this.trigger('Error', {
- code : self.FILE_COUNT_ERROR,
- message : _("File count error."),
- file : file
- });
- cb(false);
- } else {
- cb(true);
- }
- });
- uploader.bind('Error', function(up, err) {
- var message, details = "";
- message = '<strong>' + err.message + '</strong>';
-
- switch (err.code) {
- case plupload.FILE_EXTENSION_ERROR:
- details = o.sprintf(_("File: %s"), err.file.name);
- break;
-
- case plupload.FILE_SIZE_ERROR:
- details = o.sprintf(_("File: %s, size: %d, max file size: %d"), err.file.name, plupload.formatSize(err.file.size), plupload.formatSize(plupload.parseSize(up.getOption('filters').max_file_size)));
- break;
- case plupload.FILE_DUPLICATE_ERROR:
- details = o.sprintf(_("%s already present in the queue."), err.file.name);
- break;
-
- case self.FILE_COUNT_ERROR:
- details = o.sprintf(_("Upload element accepts only %d file(s) at a time. Extra files were stripped."), up.getOption('filters').max_file_count || 0);
- break;
-
- case plupload.IMAGE_FORMAT_ERROR :
- details = _("Image format either wrong or not supported.");
- break;
-
- case plupload.IMAGE_MEMORY_ERROR :
- details = _("Runtime ran out of available memory.");
- break;
-
- /* // This needs a review
- case plupload.IMAGE_DIMENSIONS_ERROR :
- details = o.sprintf(_('Resoultion out of boundaries! <b>%s</b> runtime supports images only up to %wx%hpx.'), up.runtime, up.features.maxWidth, up.features.maxHeight);
- break; */
-
- case plupload.HTTP_ERROR:
- details = _("Upload URL might be wrong or doesn't exist.");
- break;
- }
- message += " <br /><i>" + details + "</i>";
- self._trigger('error', null, { up: up, error: err } );
- // do not show UI if no runtime can be initialized
- if (err.code === plupload.INIT_ERROR) {
- setTimeout(function() {
- self.destroy();
- }, 1);
- } else {
- self.notify('error', message);
- }
- });
-
- uploader.bind('PostInit', function(up) {
- // all buttons are optional, so they can be disabled and hidden
- if (!self.options.buttons.browse) {
- self.browse_button.button('disable').hide();
- up.disableBrowse(true);
- } else {
- self.browse_button.button('enable');
- }
-
- if (!self.options.buttons.start) {
- self.start_button.button('disable').hide();
- }
-
- if (!self.options.buttons.stop) {
- self.stop_button.button('disable').hide();
- }
-
- if (!self.options.unique_names && self.options.rename) {
- self._enableRenaming();
- }
- if (self.options.dragdrop && up.features.dragdrop) {
- self.filelist.parent().addClass('plupload_dropbox');
- }
- self._enableViewSwitcher();
-
- self.start_button.click(function(e) {
- if (!$(this).button('option', 'disabled')) {
- self.start();
- }
- e.preventDefault();
- });
- self.stop_button.click(function(e) {
- self.stop();
- e.preventDefault();
- });
- self._trigger('ready', null, { up: up });
- });
-
- // uploader internal events must run first
- uploader.init();
- uploader.bind('FileFiltered', function(up, file) {
- self._addFiles(file);
- });
-
- uploader.bind('FilesAdded', function(up, files) {
- self._trigger('selected', null, { up: up, files: files } );
- // re-enable sortable
- if (self.options.sortable && $.ui.sortable) {
- self._enableSortingList();
- }
- self._trigger('updatelist', null, { filelist: self.filelist });
-
- if (self.options.autostart) {
- // set a little delay to make sure that QueueChanged triggered by the core has time to complete
- setTimeout(function() {
- self.start();
- }, 10);
- }
- });
-
- uploader.bind('FilesRemoved', function(up, files) {
- // destroy sortable if enabled
- if ($.ui.sortable && self.options.sortable) {
- $('tbody', self.filelist).sortable('destroy');
- }
- $.each(files, function(i, file) {
- $('#' + file.id).toggle("highlight", function() {
- $(this).remove();
- });
- });
-
- if (up.files.length) {
- // re-initialize sortable
- if (self.options.sortable && $.ui.sortable) {
- self._enableSortingList();
- }
- }
- self._trigger('updatelist', null, { filelist: self.filelist });
- self._trigger('removed', null, { up: up, files: files } );
- });
-
- uploader.bind('QueueChanged StateChanged', function() {
- self._handleState();
- });
-
- uploader.bind('UploadFile', function(up, file) {
- self._handleFileStatus(file);
- });
-
- uploader.bind('FileUploaded', function(up, file) {
- self._handleFileStatus(file);
- self._trigger('uploaded', null, { up: up, file: file } );
- });
-
- uploader.bind('UploadProgress', function(up, file) {
- self._handleFileStatus(file);
- self._updateTotalProgress();
- self._trigger('progress', null, { up: up, file: file } );
- });
-
- uploader.bind('UploadComplete', function(up, files) {
- self._addFormFields();
- self._trigger('complete', null, { up: up, files: files } );
- });
- },
-
- _setOption: function(key, value) {
- var self = this;
- if (key == 'buttons' && typeof(value) == 'object') {
- value = $.extend(self.options.buttons, value);
-
- if (!value.browse) {
- self.browse_button.button('disable').hide();
- self.uploader.disableBrowse(true);
- } else {
- self.browse_button.button('enable').show();
- self.uploader.disableBrowse(false);
- }
-
- if (!value.start) {
- self.start_button.button('disable').hide();
- } else {
- self.start_button.button('enable').show();
- }
-
- if (!value.stop) {
- self.stop_button.button('disable').hide();
- } else {
- self.start_button.button('enable').show();
- }
- }
-
- self.uploader.settings[key] = value;
- },
-
- /**
- Start upload. Triggers `start` event.
- @method start
- */
- start: function() {
- this.uploader.start();
- this._trigger('start', null, { up: this.uploader });
- },
-
- /**
- Stop upload. Triggers `stop` event.
- @method stop
- */
- stop: function() {
- this.uploader.stop();
- this._trigger('stop', null, { up: this.uploader });
- },
- /**
- Enable browse button.
- @method enable
- */
- enable: function() {
- this.browse_button.button('enable');
- this.uploader.disableBrowse(false);
- },
- /**
- Disable browse button.
- @method disable
- */
- disable: function() {
- this.browse_button.button('disable');
- this.uploader.disableBrowse(true);
- },
-
- /**
- Retrieve file by it's unique id.
- @method getFile
- @param {String} id Unique id of the file
- @return {plupload.File}
- */
- getFile: function(id) {
- var file;
-
- if (typeof id === 'number') {
- file = this.uploader.files[id];
- } else {
- file = this.uploader.getFile(id);
- }
- return file;
- },
- /**
- Return array of files currently in the queue.
-
- @method getFiles
- @return {Array} Array of files in the queue represented by plupload.File objects
- */
- getFiles: function() {
- return this.uploader.files;
- },
-
- /**
- Remove the file from the queue.
- @method removeFile
- @param {plupload.File|String} file File to remove, might be specified directly or by it's unique id
- */
- removeFile: function(file) {
- if (plupload.typeOf(file) === 'string') {
- file = this.getFile(file);
- }
- this.uploader.removeFile(file);
- },
-
- /**
- Clear the file queue.
- @method clearQueue
- */
- clearQueue: function() {
- this.uploader.splice();
- },
- /**
- Retrieve internal plupload.Uploader object (usually not required).
- @method getUploader
- @return {plupload.Uploader}
- */
- getUploader: function() {
- return this.uploader;
- },
- /**
- Trigger refresh procedure, specifically browse_button re-measure and re-position operations.
- Might get handy, when UI Widget is placed within the popup, that is constantly hidden and shown
- again - without calling this method after each show operation, dialog trigger might get displaced
- and disfunctional.
- @method refresh
- */
- refresh: function() {
- this.uploader.refresh();
- },
- /**
- Display a message in notification area.
- @method notify
- @param {Enum} type Type of the message, either `error` or `info`
- @param {String} message The text message to display.
- */
- notify: function(type, message) {
- var popup = $(
- '<div class="plupload_message">' +
- '<span class="plupload_message_close ui-icon ui-icon-circle-close" title="'+_('Close')+'"></span>' +
- '<p><span class="ui-icon"></span>' + message + '</p>' +
- '</div>'
- );
-
- popup
- .addClass('ui-state-' + (type === 'error' ? 'error' : 'highlight'))
- .find('p .ui-icon')
- .addClass('ui-icon-' + (type === 'error' ? 'alert' : 'info'))
- .end()
- .find('.plupload_message_close')
- .click(function() {
- popup.remove();
- })
- .end();
-
- $('.plupload_header', this.container).append(popup);
- },
-
- /**
- Destroy the widget, the uploader, free associated resources and bring back original html.
- @method destroy
- */
- destroy: function() {
- // destroy uploader instance
- this.uploader.destroy();
- // unbind all button events
- $('.plupload_button', this.element).unbind();
-
- // destroy buttons
- if ($.ui.button) {
- $('.plupload_add, .plupload_start, .plupload_stop', this.container)
- .button('destroy');
- }
-
- // destroy progressbar
- if ($.ui.progressbar) {
- this.progressbar.progressbar('destroy');
- }
-
- // destroy sortable behavior
- if ($.ui.sortable && this.options.sortable) {
- $('tbody', this.filelist).sortable('destroy');
- }
-
- // restore the elements initial state
- this.element
- .empty()
- .html(this.contents_bak);
- this.contents_bak = '';
- $.Widget.prototype.destroy.apply(this);
- },
-
-
- _handleState: function() {
- var up = this.uploader
- , filesPending = up.files.length - (up.total.uploaded + up.total.failed)
- , maxCount = up.getOption('filters').max_file_count || 0
- ;
-
- if (plupload.STARTED === up.state) {
- $([])
- .add(this.stop_button)
- .add('.plupload_started')
- .removeClass('plupload_hidden');
- this.start_button.button('disable');
- if (!this.options.multiple_queues) {
- this.browse_button.button('disable');
- up.disableBrowse();
- }
-
- $('.plupload_upload_status', this.element).html(o.sprintf(_('Uploaded %d/%d files'), up.total.uploaded, up.files.length));
- $('.plupload_header_content', this.element).addClass('plupload_header_content_bw');
- }
- else if (plupload.STOPPED === up.state) {
- $([])
- .add(this.stop_button)
- .add('.plupload_started')
- .addClass('plupload_hidden');
- if (filesPending) {
- this.start_button.button('enable');
- } else {
- this.start_button.button('disable');
- }
-
- if (this.options.multiple_queues) {
- $('.plupload_header_content', this.element).removeClass('plupload_header_content_bw');
- }
- // if max_file_count defined, only that many files can be queued at once
- if (this.options.multiple_queues && maxCount && maxCount > filesPending) {
- this.browse_button.button('enable');
- up.disableBrowse(false);
- }
- this._updateTotalProgress();
- }
- if (up.total.queued === 0) {
- $('.ui-button-text', this.browse_button).html(_('Add Files'));
- } else {
- $('.ui-button-text', this.browse_button).html(o.sprintf(_('%d files queued'), up.total.queued));
- }
- up.refresh();
- },
-
- _handleFileStatus: function(file) {
- var $file = $('#' + file.id), actionClass, iconClass;
-
- // since this method might be called asynchronously, file row might not yet be rendered
- if (!$file.length) {
- return;
- }
- switch (file.status) {
- case plupload.DONE:
- actionClass = 'plupload_done';
- iconClass = 'plupload_action_icon ui-icon ui-icon-circle-check';
- break;
-
- case plupload.FAILED:
- actionClass = 'ui-state-error plupload_failed';
- iconClass = 'plupload_action_icon ui-icon ui-icon-alert';
- break;
- case plupload.QUEUED:
- actionClass = 'plupload_delete';
- iconClass = 'plupload_action_icon ui-icon ui-icon-circle-minus';
- break;
- case plupload.UPLOADING:
- actionClass = 'ui-state-highlight plupload_uploading';
- iconClass = 'plupload_action_icon ui-icon ui-icon-circle-arrow-w';
-
- // scroll uploading file into the view if its bottom boundary is out of it
- var scroller = $('.plupload_scroll', this.container)
- , scrollTop = scroller.scrollTop()
- , scrollerHeight = scroller.height()
- , rowOffset = $file.position().top + $file.height()
- ;
-
- if (scrollerHeight < rowOffset) {
- scroller.scrollTop(scrollTop + rowOffset - scrollerHeight);
- }
- // Set file specific progress
- $file
- .find('.plupload_file_percent')
- .html(file.percent + '%')
- .end()
- .find('.plupload_file_progress')
- .css('width', file.percent + '%')
- .end()
- .find('.plupload_file_size')
- .html(plupload.formatSize(file.size));
- break;
- }
- actionClass += ' ui-state-default plupload_file';
- $file
- .attr('class', actionClass)
- .find('.plupload_action_icon')
- .attr('class', iconClass);
- },
-
-
- _updateTotalProgress: function() {
- var up = this.uploader;
- // Scroll to end of file list
- this.filelist[0].scrollTop = this.filelist[0].scrollHeight;
-
- this.progressbar.progressbar('value', up.total.percent);
-
- this.element
- .find('.plupload_total_status')
- .html(up.total.percent + '%')
- .end()
- .find('.plupload_total_file_size')
- .html(plupload.formatSize(up.total.size))
- .end()
- .find('.plupload_upload_status')
- .html(o.sprintf(_('Uploaded %d/%d files'), up.total.uploaded, up.files.length));
- },
- _displayThumbs: function() {
- var self = this
- , tw, th // thumb width/height
- , cols
- , num = 0 // number of simultaneously visible thumbs
- , thumbs = [] // array of thumbs to preload at any given moment
- , loading = false
- ;
- if (!this.options.views.thumbs) {
- return;
- }
- function onLast(el, eventName, cb) {
- var timer;
-
- el.on(eventName, function() {
- clearTimeout(timer);
- timer = setTimeout(function() {
- clearTimeout(timer);
- cb();
- }, 300);
- });
- }
- // calculate number of simultaneously visible thumbs
- function measure() {
- if (!tw || !th) {
- var wrapper = $('.plupload_file:eq(0)', self.filelist);
- tw = wrapper.outerWidth(true);
- th = wrapper.outerHeight(true);
- }
- var aw = self.content.width(), ah = self.content.height();
- cols = Math.floor(aw / tw);
- num = cols * (Math.ceil(ah / th) + 1);
- }
- function pickThumbsToLoad() {
- // calculate index of virst visible thumb
- var startIdx = Math.floor(self.content.scrollTop() / th) * cols;
- // get potentially visible thumbs that are not yet visible
- thumbs = $('.plupload_file', self.filelist)
- .slice(startIdx, startIdx + num)
- .filter('.plupload_file_loading')
- .get();
- }
-
- function init() {
- function mpl() { // measure, pick, load
- if (self.view_mode !== 'thumbs') {
- return;
- }
- measure();
- pickThumbsToLoad();
- lazyLoad();
- }
- if ($.fn.resizable) {
- onLast(self.container, 'resize', mpl);
- }
- onLast(self.window, 'resize', mpl);
- onLast(self.content, 'scroll', mpl);
- self.element.on('viewchanged selected', mpl);
- mpl();
- }
- function preloadThumb(file, cb) {
- var img = new o.Image();
- img.onload = function() {
- var thumb = $('#' + file.id + ' .plupload_file_thumb', self.filelist).html('');
- this.embed(thumb[0], {
- width: self.options.thumb_width,
- height: self.options.thumb_height,
- crop: true,
- swf_url: o.resolveUrl(self.options.flash_swf_url),
- xap_url: o.resolveUrl(self.options.silverlight_xap_url)
- });
- };
- img.bind("embedded error", function() {
- $('#' + file.id, self.filelist).removeClass('plupload_file_loading');
- this.destroy();
- setTimeout(cb, 1); // detach, otherwise ui might hang (in SilverLight for example)
- });
- img.load(file.getSource());
- }
- function lazyLoad() {
- if (self.view_mode !== 'thumbs' || loading) {
- return;
- }
- pickThumbsToLoad();
- if (!thumbs.length) {
- return;
- }
- loading = true;
- preloadThumb(self.getFile($(thumbs.shift()).attr('id')), function() {
- loading = false;
- lazyLoad();
- });
- }
- // this has to run only once to measure structures and bind listeners
- this.element.on('selected', function onselected() {
- self.element.off('selected', onselected);
- init();
- });
- },
- _addFiles: function(files) {
- var self = this, file_html, html = '';
- file_html = '<li class="plupload_file ui-state-default plupload_file_loading plupload_delete" id="%id%" style="width:%thumb_width%px;">' +
- '<div class="plupload_file_thumb" style="width:%thumb_width%px;height:%thumb_height%px;">' +
- '<div class="plupload_file_dummy ui-widget-content" style="line-height:%thumb_height%px;"><span class="ui-state-disabled">%ext% </span></div>' +
- '</div>' +
- '<div class="plupload_file_status">' +
- '<div class="plupload_file_progress ui-widget-header" style="width: 0%"> </div>' +
- '<span class="plupload_file_percent">%percent% </span>' +
- '</div>' +
- '<div class="plupload_file_name" title="%name%">' +
- '<span class="plupload_file_name_wrapper">%name% </span>' +
- '</div>' +
- '<div class="plupload_file_action">' +
- '<div class="plupload_action_icon ui-icon ui-icon-circle-minus"> </div>' +
- '</div>' +
- '<div class="plupload_file_size">%size% </div>' +
- '<div class="plupload_file_fields"> </div>' +
- '</li>';
- if (plupload.typeOf(files) !== 'array') {
- files = [files];
- }
- $.each(files, function(i, file) {
- var ext = o.Mime.getFileExtension(file.name) || 'none';
- html += file_html.replace(/%(\w+)%/g, function($0, $1) {
- switch ($1) {
- case 'thumb_width':
- case 'thumb_height':
- return self.options[$1];
-
- case 'size':
- return plupload.formatSize(file.size);
- case 'ext':
- return ext;
- default:
- return file[$1] || '';
- }
- });
- });
- self.filelist.append(html);
- },
- _addFormFields: function() {
- var self = this;
- // re-add from fresh
- $('.plupload_file_fields', this.filelist).html('');
- plupload.each(this.uploader.files, function(file, count) {
- var fields = ''
- , id = self.id + '_' + count
- ;
- if (file.target_name) {
- fields += '<input type="hidden" name="' + id + '_tmpname" value="'+plupload.xmlEncode(file.target_name)+'" />';
- }
- fields += '<input type="hidden" name="' + id + '_name" value="'+plupload.xmlEncode(file.name)+'" />';
- fields += '<input type="hidden" name="' + id + '_status" value="' + (file.status === plupload.DONE ? 'done' : 'failed') + '" />';
- $('#' + file.id).find('.plupload_file_fields').html(fields);
- });
- this.counter.val(this.uploader.files.length);
- },
-
- _viewChanged: function(view) {
- // update or write a new cookie
- if (this.options.views.remember && $.cookie) {
- $.cookie('plupload_ui_view', view, { expires: 7, path: '/' });
- }
-
- // ugly fix for IE6 - make content area stretchable
- if (o.Env.browser === 'IE' && o.Env.version < 7) {
- this.content.attr('style', 'height:expression(document.getElementById("' + this.id + '_container' + '").clientHeight - ' + (view === 'list' ? 132 : 102) + ')');
- }
- this.container.removeClass('plupload_view_list plupload_view_thumbs').addClass('plupload_view_' + view);
- this.view_mode = view;
- this._trigger('viewchanged', null, { view: view });
- },
- _enableViewSwitcher: function() {
- var self = this
- , view
- , switcher = $('.plupload_view_switch', this.container)
- , buttons
- , button
- ;
- plupload.each(['list', 'thumbs'], function(view) {
- if (!self.options.views[view]) {
- switcher.find('[for="' + self.id + '_view_' + view + '"], #'+ self.id +'_view_' + view).remove();
- }
- });
- // check if any visible left
- buttons = switcher.find('.plupload_button');
- if (buttons.length === 1) {
- switcher.hide();
- view = buttons.eq(0).data('view');
- this._viewChanged(view);
- } else if ($.ui.button && buttons.length > 1) {
- if (this.options.views.remember && $.cookie) {
- view = $.cookie('plupload_ui_view');
- }
- // if wierd case, bail out to default
- if (!~plupload.inArray(view, ['list', 'thumbs'])) {
- view = this.options.views.active;
- }
- switcher
- .show()
- .buttonset()
- .find('.ui-button')
- .click(function(e) {
- view = $(this).data('view');
- self._viewChanged(view);
- e.preventDefault(); // avoid auto scrolling to widget in IE and FF (see #850)
- });
- // if view not active - happens when switcher wasn't clicked manually
- button = switcher.find('[for="' + self.id + '_view_'+view+'"]');
- if (button.length) {
- button.trigger('click');
- }
- } else {
- switcher.show();
- this._viewChanged(this.options.views.active);
- }
- // initialize thumb viewer if requested
- if (this.options.views.thumbs) {
- this._displayThumbs();
- }
- },
-
-
- _enableRenaming: function() {
- var self = this;
- this.filelist.dblclick(function(e) {
- var nameSpan = $(e.target), nameInput, file, parts, name, ext = "";
- if (!nameSpan.hasClass('plupload_file_name_wrapper')) {
- return;
- }
-
- // Get file name and split out name and extension
- file = self.uploader.getFile(nameSpan.closest('.plupload_file')[0].id);
- name = file.name;
- parts = /^(.+)(\.[^.]+)$/.exec(name);
- if (parts) {
- name = parts[1];
- ext = parts[2];
- }
- // Display input element
- nameInput = $('<input class="plupload_file_rename" type="text" />').width(nameSpan.width()).insertAfter(nameSpan.hide());
- nameInput.val(name).blur(function() {
- nameSpan.show().parent().scrollLeft(0).end().next().remove();
- }).keydown(function(e) {
- var nameInput = $(this);
- if ($.inArray(e.keyCode, [13, 27]) !== -1) {
- e.preventDefault();
- // Rename file and glue extension back on
- if (e.keyCode === 13) {
- file.name = nameInput.val() + ext;
- nameSpan.html(file.name);
- }
- nameInput.blur();
- }
- })[0].focus();
- });
- },
-
-
- _enableSortingList: function() {
- var self = this;
-
- if ($('.plupload_file', this.filelist).length < 2) {
- return;
- }
- // destroy sortable if enabled
- $('tbody', this.filelist).sortable('destroy');
-
- // enable
- this.filelist.sortable({
- items: '.plupload_delete',
-
- cancel: 'object, .plupload_clearer',
- stop: function() {
- var files = [];
-
- $.each($(this).sortable('toArray'), function(i, id) {
- files[files.length] = self.uploader.getFile(id);
- });
-
- files.unshift(files.length);
- files.unshift(0);
-
- // re-populate files array
- Array.prototype.splice.apply(self.uploader.files, files);
- }
- });
- }
- });
- } (window, document, plupload, mOxie, jQuery));
|