PageSourceSearch

https://sge.feemg.com.br/global/plugins/jquery-file-upload/js/jquery.fileupload-ui.js

js feemg.com.br collected 2026-10-04 01:46:11 UTC 28,558 bytes, 710 lines download raw bytes

1/*
2 * jQuery File Upload User Interface Plugin
3 * https://github.com/blueimp/jQuery-File-Upload
4 *
5 * Copyright 2010, Sebastian Tschan
6 * https://blueimp.net
7 *
8 * Licensed under the MIT license:
9 * http://www.opensource.org/licenses/MIT
10 */
11
12/* jshint nomen:false */
13/* global define, require, window */
14
15(function (factory) {
16    'use strict';
17    if (typeof define === 'function' && define.amd) {
18        // Register as an anonymous AMD module:
19        define([
20            'jquery',
21            'tmpl',
22            './jquery.fileupload-image',
23            './jquery.fileupload-audio',
24            './jquery.fileupload-video',
25            './jquery.fileupload-validate'
26        ], factory);
27    } else if (typeof exports === 'object') {
28        // Node/CommonJS:
29        factory(
30            require('jquery'),
31            require('tmpl')
32        );
33    } else {
34        // Browser globals:
35        factory(
36            window.jQuery,
37            window.tmpl
38        );
39    }
40}(function ($, tmpl) {
41    'use strict';
42
43    $.blueimp.fileupload.prototype._specialOptions.push(
44        'filesContainer',
45        'uploadTemplateId',
46        'downloadTemplateId'
47    );
48
49    // The UI version extends the file upload widget
50    // and adds complete user interface interaction:
51    $.widget('blueimp.fileupload', $.blueimp.fileupload, {
52
53        options: {
54            // By default, files added to the widget are uploaded as soon
55            // as the user clicks on the start buttons. To enable automatic
56            // uploads, set the following option to true:
57            autoUpload: false,
58            // The ID of the upload template:
59            uploadTemplateId: 'template-upload',
60            // The ID of the download template:
61            downloadTemplateId: 'template-download',
62            // The container for the list of files. If undefined, it is set to
63            // an element with class "files" inside of the widget element:
64            filesContainer: undefined,
65            // By default, files are appended to the files container.
66            // Set the following option to true, to prepend files instead:
67            prependFiles: false,
68            // The expected data type of the upload response, sets the dataType
69            // option of the $.ajax upload requests:
70            dataType: 'json',
71
72            // Error and info messages:
73            messages: {
74                unknownError: 'Unknown error'
75            },
76
77            // Function returning the current number of files,
78            // used by the maxNumberOfFiles validation:
79            getNumberOfFiles: function () {
80                return this.filesContainer.children()
81                    .not('.processing').length;
82            },
83
84            // Callback to retrieve the list of files from the server response:
85            getFilesFromResponse: function (data) {
86                if (data.result && $.isArray(data.result.files)) {
87                    return data.result.files;
88                }
89                return [];
90            },
91
92            // The add callback is invoked as soon as files are added to the fileupload
93            // widget (via file input selection, drag & drop or add API call).
94            // See the basic file upload widget for more information:
95            add: function (e, data) {
96                if (e.isDefaultPrevented()) {
97                    return false;
98                }
99                var $this = $(this),
100                    that = $this.data('blueimp-fileupload') ||
101                        $this.data('fileupload'),
102                    options = that.options;
103                data.context = that._renderUpload(data.files)
104                    .data('data', data)
105                    .addClass('processing');
106                options.filesContainer[
107                    options.prependFiles ? 'prepend' : 'append'
108                ](data.context);
109                that._forceReflow(data.context);
110                that._transition(data.context);
111                data.process(function () {
112                    return $this.fileupload('process', data);
113                }).always(function () {
114                    data.context.each(function (index) {
115                        $(this).find('.size').text(
116                            that._formatFileSize(data.files[index].size)
117                        );
118                    }).removeClass('processing');
119                    that._renderPreviews(data);
120                }).done(function () {
121                    data.context.find('.start').prop('disabled', false);
122                    if ((that._trigger('added', e, data) !== false) &&
123                            (options.autoUpload || data.autoUpload) &&
124                            data.autoUpload !== false) {
125                        data.submit();
126                    }
127                }).fail(function () {
128                    if (data.files.error) {
129                        data.context.each(function (index) {
130                            var error = data.files[index].error;
131                            if (error) {
132                                $(this).find('.error').text(error);
133                            }
134                        });
135                    }
136                });
137            },
138            // Callback for the start of each file upload request:
139            send: function (e, data) {
140                if (e.isDefaultPrevented()) {
141                    return false;
142                }
143                var that = $(this).data('blueimp-fileupload') ||
144                        $(this).data('fileupload');
145                if (data.context && data.dataType &&
146                        data.dataType.substr(0, 6) === 'iframe') {
147                    // Iframe Transport does not support progress events.
148                    // In lack of an indeterminate progress bar, we set
149                    // the progress to 100%, showing the full animated bar:
150                    data.context
151                        .find('.progress').addClass(
152                            !$.support.transition && 'progress-animated'
153                        )
154                        .attr('aria-valuenow', 100)
155                        .children().first().css(
156                            'width',
157                            '100%'
158                        );
159                }
160                return that._trigger('sent', e, data);
161            },
162            // Callback for successful uploads:
163            done: function (e, data) {
164                if (e.isDefaultPrevented()) {
165                    return false;
166                }
167                var that = $(this).data('blueimp-fileupload') ||
168                        $(this).data('fileupload'),
169                    getFilesFromResponse = data.getFilesFromResponse ||
170                        that.options.getFilesFromResponse,
171                    files = getFilesFromResponse(data),
172                    template,
173                    deferred;
174                if (data.context) {
175                    data.context.each(function (index) {
176                        var file = files[index] ||
177                                {error: 'Empty file upload result'};
178                        deferred = that._addFinishedDeferreds();
179                        that._transition($(this)).done(
180                            function () {
181                                var node = $(this);
182                                template = that._renderDownload([file])
183                                    .replaceAll(node);
184                                that._forceReflow(template);
185                                that._transition(template).done(
186                                    function () {
187                                        data.context = $(this);
188                                        that._trigger('completed', e, data);
189                                        that._trigger('finished', e, data);
190                                        deferred.resolve();
191                                    }
192                                );
193                            }
194                        );
195                    });
196                } else {
197                    template = that._renderDownload(files)[
198                        that.options.prependFiles ? 'prependTo' : 'appendTo'
199                    ](that.options.filesContainer);
200                    that._forceReflow(template);
201                    deferred = that._addFinishedDeferreds();
202                    that._transition(template).done(
203                        function () {
204                            data.context = $(this);
205                            that._trigger('completed', e, data);
206                            that._trigger('finished', e, data);
207                            deferred.resolve();
208                        }
209                    );
210                }
211            },
212            // Callback for failed (abort or error) uploads:
213            fail: function (e, data) {
214                if (e.isDefaultPrevented()) {
215                    return false;
216                }
217                var that = $(this).data('blueimp-fileupload') ||
218                        $(this).data('fileupload'),
219                    template,
220                    deferred;
221                if (data.context) {
222                    data.context.each(function (index) {
223                        if (data.errorThrown !== 'abort') {
224                            var file = data.files[index];
225                            file.error = file.error || data.errorThrown ||
226                                data.i18n('unknownError');
227                            deferred = that._addFinishedDeferreds();
228                            that._transition($(this)).done(
229                                function () {
230                                    var node = $(this);
231                                    template = that._renderDownload([file])
232                                        .replaceAll(node);
233                                    that._forceReflow(template);
234                                    that._transition(template).done(
235                                        function () {
236                                            data.context = $(this);
237                                            that._trigger('failed', e, data);
238                                            that._trigger('finished', e, data);
239                                            deferred.resolve();
240                                        }
241                                    );
242                                }
243                            );
244                        } else {
245                            deferred = that._addFinishedDeferreds();
246                            that._transition($(this)).done(
247                                function () {
248                                    $(this).remove();
249                                    that._trigger('failed', e, data);
250                                    that._trigger('finished', e, data);
251                                    deferred.resolve();
252                                }
253                            );
254                        }
255                    });
256                } else if (data.errorThrown !== 'abort') {
257                    data.context = that._renderUpload(data.files)[
258                        that.options.prependFiles ? 'prependTo' : 'appendTo'
259                    ](that.options.filesContainer)
260                        .data('data', data);
261                    that._forceReflow(data.context);
262                    deferred = that._addFinishedDeferreds();
263                    that._transition(data.context).done(
264                        function () {
265                            data.context = $(this);
266                            that._trigger('failed', e, data);
267                            that._trigger('finished', e, data);
268                            deferred.resolve();
269                        }
270                    );
271                } else {
272                    that._trigger('failed', e, data);
273                    that._trigger('finished', e, data);
274                    that._addFinishedDeferreds().resolve();
275                }
276            },
277            // Callback for upload progress events:
278            progress: function (e, data) {
279                if (e.isDefaultPrevented()) {
280                    return false;
281                }
282                var progress = Math.floor(data.loaded / data.total * 100);
283                if (data.context) {
284                    data.context.each(function () {
285                        $(this).find('.progress')
286                            .attr('aria-valuenow', progress)
287                            .children().first().css(
288                                'width',
289                                progress + '%'
290                            );
291                    });
292                }
293            },
294            // Callback for global upload progress events:
295            progressall: function (e, data) {
296                if (e.isDefaultPrevented()) {
297                    return false;
298                }
299                var $this = $(this),
300                    progress = Math.floor(data.loaded / data.total * 100),
301                    globalProgressNode = $this.find('.fileupload-progress'),
302                    extendedProgressNode = globalProgressNode
303                        .find('.progress-extended');
304                if (extendedProgressNode.length) {
305                    extendedProgressNode.html(
306                        ($this.data('blueimp-fileupload') || $this.data('fileupload'))
307                            ._renderExtendedProgress(data)
308                    );
309                }
310                globalProgressNode
311                    .find('.progress')
312                    .attr('aria-valuenow', progress)
313                    .children().first().css(
314                        'width',
315                        progress + '%'
316                    );
317            },
318            // Callback for uploads start, equivalent to the global ajaxStart event:
319            start: function (e) {
320                if (e.isDefaultPrevented()) {
321                    return false;
322                }
323                var that = $(this).data('blueimp-fileupload') ||
324                        $(this).data('fileupload');
325                that._resetFinishedDeferreds();
326                that._transition($(this).find('.fileupload-progress')).done(
327                    function () {
328                        that._trigger('started', e);
329                    }
330                );
331            },
332            // Callback for uploads stop, equivalent to the global ajaxStop event:
333            stop: function (e) {
334                if (e.isDefaultPrevented()) {
335                    return false;
336                }
337                var that = $(this).data('blueimp-fileupload') ||
338                        $(this).data('fileupload'),
339                    deferred = that._addFinishedDeferreds();
340                $.when.apply($, that._getFinishedDeferreds())
341                    .done(function () {
342                        that._trigger('stopped', e);
343                    });
344                that._transition($(this).find('.fileupload-progress')).done(
345                    function () {
346                        $(this).find('.progress')
347                            .attr('aria-valuenow', '0')
348                            .children().first().css('width', '0%');
349                        $(this).find('.progress-extended').html(' ');
350                        deferred.resolve();
351                    }
352                );
353            },
354            processstart: function (e) {
355                if (e.isDefaultPrevented()) {
356                    return false;
357                }
358                $(this).addClass('fileupload-processing');
359            },
360            processstop: function (e) {
361                if (e.isDefaultPrevented()) {
362                    return false;
363                }
364                $(this).removeClass('fileupload-processing');
365            },
366            // Callback for file deletion:
367            destroy: function (e, data) {
368                if (e.isDefaultPrevented()) {
369                    return false;
370                }
371                var that = $(this).data('blueimp-fileupload') ||
372                        $(this).data('fileupload'),
373                    removeNode = function () {
374                        that._transition(data.context).done(
375                            function () {
376                                $(this).remove();
377                                that._trigger('destroyed', e, data);
378                            }
379                        );
380                    };
381                if (data.url) {
382                    data.dataType = data.dataType || that.options.dataType;
383                    $.ajax(data).done(removeNode).fail(function () {
384                        that._trigger('destroyfailed', e, data);
385                    });
386                } else {
387                    removeNode();
388                }
389            }
390        },
391
392        _resetFinishedDeferreds: function () {
393            this._finishedUploads = [];
394        },
395
396        _addFinishedDeferreds: function (deferred) {
397            if (!deferred) {
398                deferred = $.Deferred();
399            }
400            this._finishedUploads.push(deferred);
401            return deferred;
402        },
403
404        _getFinishedDeferreds: function () {
405            return this._finishedUploads;
406        },
407
408        // Link handler, that allows to download files
409        // by drag & drop of the links to the desktop:
410        _enableDragToDesktop: function () {
411            var link = $(this),
412                url = link.prop('href'),
413                name = link.prop('download'),
414                type = 'application/octet-stream';
415            link.bind('dragstart', function (e) {
416                try {
417                    e.originalEvent.dataTransfer.setData(
418                        'DownloadURL',
419                        [type, name, url].join(':')
420                    );
421                } catch (ignore) {}
422            });
423        },
424
425        _formatFileSize: function (bytes) {
426            if (typeof bytes !== 'number') {
427                return '';
428            }
429            if (bytes >= 1000000000) {
430                return (bytes / 1000000000).toFixed(2) + ' GB';
431            }
432            if (bytes >= 1000000) {
433                return (bytes / 1000000).toFixed(2) + ' MB';
434            }
435            return (bytes / 1000).toFixed(2) + ' KB';
436        },
437
438        _formatBitrate: function (bits) {
439            if (typeof bits !== 'number') {
440                return '';
441            }
442            if (bits >= 1000000000) {
443                return (bits / 1000000000).toFixed(2) + ' Gbit/s';
444            }
445            if (bits >= 1000000) {
446                return (bits / 1000000).toFixed(2) + ' Mbit/s';
447            }
448            if (bits >= 1000) {
449                return (bits / 1000).toFixed(2) + ' kbit/s';
450            }
451            return bits.toFixed(2) + ' bit/s';
452        },
453
454        _formatTime: function (seconds) {
455            var date = new Date(seconds * 1000),
456                days = Math.floor(seconds / 86400);
457            days = days ? days + 'd ' : '';
458            return days +
459                ('0' + date.getUTCHours()).slice(-2) + ':' +
460                ('0' + date.getUTCMinutes()).slice(-2) + ':' +
461                ('0' + date.getUTCSeconds()).slice(-2);
462        },
463
464        _formatPercentage: function (floatValue) {
465            return (floatValue * 100).toFixed(2) + ' %';
466        },
467
468        _renderExtendedProgress: function (data) {
469            return this._formatBitrate(data.bitrate) + ' | ' +
470                this._formatTime(
471                    (data.total - data.loaded) * 8 / data.bitrate
472                ) + ' | ' +
473                this._formatPercentage(
474                    data.loaded / data.total
475                ) + ' | ' +
476                this._formatFileSize(data.loaded) + ' / ' +
477                this._formatFileSize(data.total);
478        },
479
480        _renderTemplate: function (func, files) {
481            if (!func) {
482                return $();
483            }
484            var result = func({
485                files: files,
486                formatFileSize: this._formatFileSize,
487                options: this.options
488            });
489            if (result instanceof $) {
490                return result;
491            }
492            return $(this.options.templatesContainer).html(result).children();
493        },
494
495        _renderPreviews: function (data) {
496            data.context.find('.preview').each(function (index, elm) {
497                $(elm).append(data.files[index].preview);
498            });
499        },
500
501        _renderUpload: function (files) {
502            return this._renderTemplate(
503                this.options.uploadTemplate,
504                files
505            );
506        },
507
508        _renderDownload: function (files) {
509            return this._renderTemplate(
510                this.options.downloadTemplate,
511                files
512            ).find('a[download]').each(this._enableDragToDesktop).end();
513        },
514
515        _startHandler: function (e) {
516            e.preventDefault();
517            var button = $(e.currentTarget),
518                template = button.closest('.template-upload'),
519                data = template.data('data');
520            button.prop('disabled', true);
521            if (data && data.submit) {
522                data.submit();
523            }
524        },
525
526        _cancelHandler: function (e) {
527            e.preventDefault();
528            var template = $(e.currentTarget)
529                    .closest('.template-upload,.template-download'),
530                data = template.data('data') || {};
531            data.context = data.context || template;
532            if (data.abort) {
533                data.abort();
534            } else {
535                data.errorThrown = 'abort';
536                this._trigger('fail', e, data);
537            }
538        },
539
540        _deleteHandler: function (e) {
541            e.preventDefault();
542            var button = $(e.currentTarget);
543            this._trigger('destroy', e, $.extend({
544                context: button.closest('.template-download'),
545                type: 'DELETE'
546            }, button.data()));
547        },
548
549        _forceReflow: function (node) {
550            return $.support.transition && node.length &&
551                node[0].offsetWidth;
552        },
553
554        _transition: function (node) {
555            var dfd = $.Deferred();
556            if ($.support.transition && node.hasClass('fade') && node.is(':visible')) {
557                node.bind(
558                    $.support.transition.end,
559                    function (e) {
560                        // Make sure we don't respond to other transitions events
561                        // in the container element, e.g. from button elements:
562                        if (e.target === node[0]) {
563                            node.unbind($.support.transition.end);
564                            dfd.resolveWith(node);
565                        }
566                    }
567                ).toggleClass('in');
568            } else {
569                node.toggleClass('in');
570                dfd.resolveWith(node);
571            }
572            return dfd;
573        },
574
575        _initButtonBarEventHandlers: function () {
576            var fileUploadButtonBar = this.element.find('.fileupload-buttonbar'),
577                filesList = this.options.filesContainer;
578            this._on(fileUploadButtonBar.find('.start'), {
579                click: function (e) {
580                    e.preventDefault();
581                    filesList.find('.start').click();
582                }
583            });
584            this._on(fileUploadButtonBar.find('.cancel'), {
585                click: function (e) {
586                    e.preventDefault();
587                    filesList.find('.cancel').click();
588                }
589            });
590            this._on(fileUploadButtonBar.find('.delete'), {
591                click: function (e) {
592                    e.preventDefault();
593                    filesList.find('.toggle:checked')
594                        .closest('.template-download')
595                        .find('.delete').click();
596                    fileUploadButtonBar.find('.toggle')
597                        .prop('checked', false);
598                }
599            });
600            this._on(fileUploadButtonBar.find('.toggle'), {
601                change: function (e) {
602                    filesList.find('.toggle').prop(
603                        'checked',
604                        $(e.currentTarget).is(':checked')
605                    );
606                }
607            });
608        },
609
610        _destroyButtonBarEventHandlers: function () {
611            this._off(
612                this.element.find('.fileupload-buttonbar')
613                    .find('.start, .cancel, .delete'),
614                'click'
615            );
616            this._off(
617                this.element.find('.fileupload-buttonbar .toggle'),
618                'change.'
619            );
620        },
621
622        _initEventHandlers: function () {
623            this._super();
624            this._on(this.options.filesContainer, {
625                'click .start': this._startHandler,
626                'click .cancel': this._cancelHandler,
627                'click .delete': this._deleteHandler
628            });
629            this._initButtonBarEventHandlers();
630        },
631
632        _destroyEventHandlers: function () {
633            this._destroyButtonBarEventHandlers();
634            this._off(this.options.filesContainer, 'click');
635            this._super();
636        },
637
638        _enableFileInputButton: function () {
639            this.element.find('.fileinput-button input')
640                .prop('disabled', false)
641                .parent().removeClass('disabled');
642        },
643
644        _disableFileInputButton: function () {
645            this.element.find('.fileinput-button input')
646                .prop('disabled', true)
647                .parent().addClass('disabled');
648        },
649
650        _initTemplates: function () {
651            var options = this.options;
652            options.templatesContainer = this.document[0].createElement(
653                options.filesContainer.prop('nodeName')
654            );
655            if (tmpl) {
656                if (options.uploadTemplateId) {
657                    options.uploadTemplate = tmpl(options.uploadTemplateId);
658                }
659                if (options.downloadTemplateId) {
660                    options.downloadTemplate = tmpl(options.downloadTemplateId);
661                }
662            }
663        },
664
665        _initFilesContainer: function () {
666            var options = this.options;
667            if (options.filesContainer === undefined) {
668                options.filesContainer = this.element.find('.files');
669            } else if (!(options.filesContainer instanceof $)) {
670                options.filesContainer = $(options.filesContainer);
671            }
672        },
673
674        _initSpecialOptions: function () {
675            this._super();
676            this._initFilesContainer();
677            this._initTemplates();
678        },
679
680        _create: function () {
681            this._super();
682            this._resetFinishedDeferreds();
683            if (!$.support.fileInput) {
684                this._disableFileInputButton();
685            }
686        },
687
688        enable: function () {
689            var wasDisabled = false;
690            if (this.options.disabled) {
691                wasDisabled = true;
692            }
693            this._super();
694            if (wasDisabled) {
695                this.element.find('input, button').prop('disabled', false);
696                this._enableFileInputButton();
697            }
698        },
699
700        disable: function () {
701            if (!this.options.disabled) {
702                this.element.find('input, button').prop('disabled', true);
703                this._disableFileInputButton();
704            }
705            this._super();
706        }
707
708    });
709
710}));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.