UNPKG

@tower1229/flow-ui

Version:

Highly customizable UI framework based Seajs/jQuery

437 lines (404 loc) 12.3 kB
/* * name: upload * version: 1.2.0 * update: 新增headers设置 * date: 2017-12-12 * base: https://github.com/aralejs/upload */ define('upload', function(require, exports, module) { 'use strict'; var $ = window.$ || require('jquery'), iframeCount = 0, DEFAULT = { trigger: null, name: null, action: null, headers: {}, data: null, accept: null, change: null, error: null, multiple: true, compress: false, compressOption: {}, success: null }; function Uploader(options) { if (!(this instanceof Uploader)) { return new Uploader(options); } if (isString(options)) { options = { trigger: options }; } var settings = $.extend({}, DEFAULT, options || {}); var $trigger = $(settings.trigger); settings.action = settings.action || $trigger.data('action') || '/upload'; settings.name = settings.name || $trigger.attr('name') || $trigger.data('name') || 'file'; settings.data = settings.data || parse($trigger.data('data')); settings.accept = settings.accept || $trigger.data('accept'); settings.success = settings.success || $trigger.data('success'); this.settings = settings; this.setup(); this.bind(); } // initialize // create input, form, iframe Uploader.prototype.setup = function() { this.form = $( '<form method="post" enctype="multipart/form-data"' + 'target="" action="' + this.settings.action + '" />' ); this.iframe = newIframe(); this.form.attr('target', this.iframe.attr('name')); var data = this.settings.data; if($.isPlainObject(data)){ this.form.append(createInputs(data)); } if (window.FormData) { this.form.append(createInputs({ '_uploader_': 'formdata' })); } else { this.form.append(createInputs({ '_uploader_': 'iframe' })); } var input = document.createElement('input'); input.type = 'file'; input.name = this.settings.name; if (this.settings.accept) { input.accept = this.settings.accept; } if (this.settings.multiple) { input.multiple = true; input.setAttribute('multiple', 'multiple'); } this.input = $(input); var $trigger = $(this.settings.trigger); this.input.attr('hidefocus', true).css({ position: 'absolute', top: 0, right: 0, opacity: 0, outline: 0, cursor: 'pointer', height: $trigger.outerHeight(), fontSize: Math.max(64, $trigger.outerHeight() * 5) }); this.form.append(this.input); this.form.css({ position: 'absolute', top: $trigger.offset().top, left: $trigger.offset().left, overflow: 'hidden', width: $trigger.outerWidth(), height: $trigger.outerHeight(), zIndex: findzIndex($trigger) + 10 }).appendTo('body'); return this; }; // bind events Uploader.prototype.bind = function() { var self = this; var $trigger = $(self.settings.trigger); $trigger.mouseenter(function() { self.form.css({ top: $trigger.offset().top, left: $trigger.offset().left, width: $trigger.outerWidth(), height: $trigger.outerHeight() }); }); self.bindInput(); }; Uploader.prototype.compressList = []; Uploader.prototype.bindInput = function() { var self = this; //缩略图 if ($.isFunction(self.settings.thumb)) { require.async('makethumb', function() { $(self.input).makeThumb($.extend({ done: function(dataURL, file) { self.settings.thumb(dataURL, file); } }, self.settings.thumbOption)); }); } self.input.change(function(e) { // ie9 don't support FileList Object // http://stackoverflow.com/questions/12830058/ie8-input-type-file-get-files self._files = this.files || [{ name: e.target.value }]; var file = self.input.val(); if (self.settings.compress) { require.async('localResizeIMG', function(lrz) { $.each(self._files, function(i, file) { lrz(file, $.extend(self.settings.compressOption, { fieldName: self.settings.name })).then(function(rst) { self.compressList.push(rst.formData); if ($.isFunction(self.settings.change)) { self.settings.change.call(self, self._files); } else if (file) { return self.submit(); } }); }); }); } else { if ($.isFunction(self.settings.change)) { self.settings.change.call(self, self._files); } else if (file) { return self.submit(); } } }); }; // handle submit event // prepare for submiting form Uploader.prototype.submit = function() { var self = this; if (window.FormData) { var form; var ajaxUpload = function(form) { var optionXhr; if (self.settings.progress) { optionXhr = function() { var xhr = $.ajaxSettings.xhr(); if (xhr.upload) { xhr.upload.addEventListener('progress', function(event) { var percent = 0; var position = event.loaded || event.position; /*event.position is deprecated*/ var total = event.total; if (event.lengthComputable) { percent = Math.ceil(position / total * 100); } self.settings.progress(event, position, total, percent); }, false); } return xhr; }; } $.ajax({ url: self.settings.action, type: 'post', headers: self.settings.headers, processData: false, contentType: false, data: form, xhr: optionXhr, context: this, success: self.settings.success, error: self.settings.error }); }; if (self.compressList.length) { $.each(self.compressList, function(i, form) { ajaxUpload(form); }); self.compressList.length = 0; self._files = null; } else { // build a FormData if(typeof self.settings.data === 'function'){ self.form.append(createInputs(self.settings.data())); } // use FormData to upload form = new FormData(self.form.get(0)); if(self._files){ form.append(self.settings.name, self._files); } ajaxUpload(form); } return this; } else if (self._files) { // iframe upload self.iframe = newIframe(); self.form.attr('target', self.iframe.attr('name')); $('body').append(self.iframe); self.iframe.one('load', function() { // https://github.com/blueimp/jQuery-File-Upload/blob/9.5.6/js/jquery.iframe-transport.js#L102 // Fix for IE endless progress bar activity bug // (happens on form submits to iframe targets): $('<iframe src="javascript:false;"></iframe>') .appendTo(self.form) .remove(); var response; try { response = $(this).contents().find("body").html(); } catch (e) { response = "cross-domain"; } $(this).remove(); if (!response) { if (self.settings.error) { self.settings.error(self.input.val()); } } else { if (self.settings.success) { self.settings.success(response); } } }); self.form.submit(); } return this; }; Uploader.prototype.refreshInput = function() { //replace the input element, or the same file can not to be uploaded var newInput = this.input.clone(); this.input.before(newInput); this.input.off('change'); this.input.remove(); this.input = newInput; this.bindInput(); }; // handle change event // when value in file input changed Uploader.prototype.change = function(callback) { if (!callback) { return this; } this.settings.change = callback; return this; }; // handle when upload success Uploader.prototype.success = function(callback) { var me = this; this.settings.success = function(response) { me.refreshInput(); if (callback) { callback(response); } }; return this; }; // handle when upload success Uploader.prototype.error = function(callback) { var me = this; this.settings.error = function(response) { if (callback) { me.refreshInput(); callback(response); } }; return this; }; // enable Uploader.prototype.enable = function() { this.input.prop('disabled', false); this.input.css('cursor', 'pointer'); }; // disable Uploader.prototype.disable = function() { this.input.prop('disabled', true); this.input.css('cursor', 'not-allowed'); }; // Helpers // ------------- function isString(val) { return Object.prototype.toString.call(val) === '[object String]'; } function createInputs(data) { if (!data) return []; var inputs = [], i; for (var name in data) { i = document.createElement('input'); i.type = 'hidden'; i.name = name; i.value = data[name]; inputs.push(i); } return inputs; } function parse(str) { if (!str) return {}; var ret = {}; var pairs = str.split('&'); var unescape = function(s) { return decodeURIComponent(s.replace(/\+/g, ' ')); }; for (var i = 0; i < pairs.length; i++) { var pair = pairs[i].split('='); var key = unescape(pair[0]); var val = unescape(pair[1]); ret[key] = val; } return ret; } function findzIndex($node) { var parents = $node.parentsUntil('body'); var zIndex = 0; for (var i = 0; i < parents.length; i++) { var item = parents.eq(i); if (item.css('position') !== 'static') { zIndex = parseInt(item.css('zIndex'), 10) || zIndex; } } return zIndex; } function newIframe() { var iframeName = 'iframe-uploader-' + iframeCount; var iframe = $('<iframe name="' + iframeName + '" />').hide(); iframeCount += 1; return iframe; } function MultipleUploader(options) { if (!(this instanceof MultipleUploader)) { return new MultipleUploader(options); } if (isString(options)) { options = { trigger: options }; } var $trigger = $(options.trigger); var uploaders = []; $trigger.each(function(i, item) { options.trigger = item; uploaders.push(new Uploader(options)); }); this._uploaders = uploaders; } MultipleUploader.prototype.submit = function() { $.each(this._uploaders, function(i, item) { item.submit(); }); return this; }; MultipleUploader.prototype.change = function(callback) { $.each(this._uploaders, function(i, item) { item.change(callback); }); return this; }; MultipleUploader.prototype.success = function(callback) { $.each(this._uploaders, function(i, item) { item.success(callback); }); return this; }; MultipleUploader.prototype.error = function(callback) { $.each(this._uploaders, function(i, item) { item.error(callback); }); return this; }; MultipleUploader.prototype.enable = function() { $.each(this._uploaders, function(i, item) { item.enable(); }); return this; }; MultipleUploader.prototype.disable = function() { $.each(this._uploaders, function(i, item) { item.disable(); }); return this; }; MultipleUploader.Uploader = Uploader; module.exports = MultipleUploader; });