From 9ad3778610c9fab685e44c7b6f673a952f49aef8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=8A=E8=BE=B9?= Date: Wed, 2 Jul 2014 16:10:59 +0800 Subject: [PATCH 01/24] add upload plugin --- js/upload.js | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 js/upload.js diff --git a/js/upload.js b/js/upload.js new file mode 100644 index 00000000..011a14da --- /dev/null +++ b/js/upload.js @@ -0,0 +1,155 @@ +(function($) { + // 注册一个ajax prefilter,创建新的type类型upload,检测ajax方法调用的入参有没有upload + $.ajaxPrefilter(function(options, origOptions, jqXHR) { + if (options.upload) { + options.originalURL = options.url; + return 'upload'; + } + }); + + // 为dataType为upload的请求类型注册一个 ajax transport + // 但他只在ajax方法调用时传入不为空的file属性才会激活.file属性是一个file input类数组 + $.ajaxTransport('upload', function(options, origOptions, jqXHR) { + var form = null, + iframe = null, + name = 'upload-' + +new Date(), + files = $(options.files).filter(':file:enabled'), + markers = null, + accepts = null; + + // 成功提交隐藏iframe内的file input后或者放弃提交后执行,使所有页面上的变化恢复原状。 + function cleanUp() { + files.each(function(k, v) { + var $file = $(v); + $file.data('clone').replaceWith($file); + }); + form.remove(); + iframe.one("load", function() { iframe.remove(); }); + iframe.attr("src", "javascript:false;"); + } + + // 从jquery ajax 的dataTypes队列中弹出第一个值,使之后数据的处理类型基于服务器返回的数据类型 + options.dataTypes.shift(); + + // 获取需要额外传输的数据 + var extraData = (options.data = origOptions.data); + + if (files.length) { + form = $('
').hide().attr({action: options.originalURL, target: name}); + + // 提交文件同时如果需要额外传输一些数据,直接放在ajax调用的data参数里 + // 但因为是附加为iframe表单的隐藏域里传值,数据不能被序列化为string。processData属性设为false即可。 + if (typeof(extraData) === 'string' && extraData.length > 0) { + throw Error('额外传输的数据不应该被序列化(serialized)'); + } + $.each(extraData || {}, function(k, v) { + if ($.isPlainObject(v)) { + k = v.name; + v = v.value; + } + $('').attr({name: k, value: v}).appendTo(form); + }); + + $('').appendTo(form); + if (options.dataTypes[0] && options.accepts[options.dataTypes[0]]) { + accepts = options.accepts[options.dataTypes[0]] + + (options.dataTypes[0] !== "*" ? ", */*; q=0.01" : ""); + } else { + accepts = options.accepts["*"]; + } + $('').attr('value', accepts).appendTo(form); + + markers = files.after(function(idx) { + var $this = $(this), + $clone = $this.clone().prop('disabled', true); + $this.data('clone', $clone); + return $clone; + }).next(); + files.appendTo(form); + + return { + // $.ajax()内部通过send方法发具体请求。自定义一个 + send: function(headers, completeCallback) { + iframe = $(''); + + // iframe被注入到DOM后触发第一个load事件,已准备提交文件 + iframe.one('load', function() { + // The second load event gets fired when the response to the form + // submission is received. The implementation detects whether the + // actual payload is embedded in a `