AjaxUpLoad.js实现无刷新文件上传

1、创建页面并编写HTML

[html] view plaincopy
 
  1. 上传文档:  
  2. <div class="uploadFile">  
  3.     <span id="doc"><input type="text" disabled="disabled" /></span>  
  4.     <input type="hidden" id="hidFileName"  />  
  5.     <input type="button" id="btnUploadFile" value="上传" />  
  6.     <input type="button" id="btnDeleteFile" value="删除"  />  
  7. </div>  
  8.   
  9. 上传图片:  
  10. <div class="uploadImg">  
  11.     <img id="imgShow" src="/images/nophoto.gif" />  
  12.     <input type="hidden" id="hidImgName" />  
  13.     <input type="button" id="btnUploadImg" value="上传" />  
  14.     <input type="button" id="btnDeleteImg" value="删除" />  
  15. </div>  

2、引用AjaxUpload.js文件

[html] view plaincopy
 
  1. <script src="js/AjaxUpload.js" type="text/javascript"></script>  

3、编写JS脚本

[java] view plaincopy
 
  1. window.onload = function() {  
  2.     init();  //初始化  
  3. }  
  4.   
  5. //初始化  
  6. function init() {  
  7.     //初始化文档上传  
  8.     var btnFile = document.getElementById("btnUploadFile");  
  9.     var doc = document.getElementById("doc");  
  10.     var hidFileName = document.getElementById("hidFileName");  
  11.     document.getElementById("btnDeleteFile").onclick = function() { DelFile(doc, hidFileName); };  
  12.     g_AjxUploadFile(btnFile, doc, hidFileName);  
  13.       
  14.     //初始化图片上传  
  15.     var btnImg = document.getElementById("btnUploadImg");  
  16.     var img = document.getElementById("imgShow");  
  17.     var hidImgName = document.getElementById("hidImgName");  
  18.     document.getElementById("btnDeleteImg").onclick = function() { DelImg(img, hidImgName); };  
  19.     g_AjxUploadImg(btnImg, img, hidImgName);  
  20. }  
  21.   
  22.   
  23. var g_AjxTempDir = "/file/temp/";  
  24. //文档上传  
  25. function g_AjxUploadFile(btn, doc, hidPut, action) {  
  26.     var button = btn, interval;  
  27.     new AjaxUpload(button, {  
  28.     action: ((action == null || action == undefined) ? '/Common/UploadHandler.ashx?fileType=file' : action),  
  29.         data: {},  
  30.         name: 'myfile',  
  31.         onSubmit: function(file, ext) {  
  32.             if (!(ext && /^(rar|zip|pdf|pdfx|txt|csv|xls|xlsx|doc|docx|RAR|ZIP|PDF|PDFX|TXT|CSV|XLS|XLSX|DOC|DOCX)$/.test(ext))) {  
  33.                 alert("您上传的文档格式不对,请重新选择!");  
  34.                 return false;  
  35.             }  
  36.         },  
  37.         onComplete: function(file, response) {  
  38.             flagValue = response;  
  39.             if (flagValue == "1") {  
  40.                 alert("您上传的文档格式不对,请重新选择!");  
  41.             }  
  42.             else if (flagValue == "2") {  
  43.                 alert("您上传的文档大于2M,请重新选择!");  
  44.             }  
  45.             else if (flagValue == "3") {  
  46.                 alert("文档上传失败!");  
  47.             }  
  48.             else {  
  49.                 hidPut.value = response;  
  50.                 doc.innerHTML="<a href='" + g_AjxTempDir + response + "' target='_blank'>" + response + "</a>";  
  51.             }  
  52.         }  
  53.     });  
  54. }  
  55. //图片上传  
  56. function g_AjxUploadImg(btn, img, hidPut) {  
  57.     var button = btn, interval;  
  58.     new AjaxUpload(button, {  
  59.         action: '/Common/UploadHandler.ashx?fileType=img',  
  60.         data: {},  
  61.         name: 'myfile',  
  62.         onSubmit: function(file, ext) {  
  63.             if (!(ext && /^(jpg|JPG|png|PNG|gif|GIF)$/.test(ext))) {  
  64.                 alert("您上传的图片格式不对,请重新选择!");  
  65.                 return false;  
  66.             }  
  67.         },  
  68.         onComplete: function(file, response) {  
  69.             flagValue = response;  
  70.             if (flagValue == "1") {  
  71.                 alert("您上传的图片格式不对,请重新选择!");  
  72.             }  
  73.             else if (flagValue == "2") {  
  74.                 alert("您上传的图片大于200K,请重新选择!");  
  75.             }  
  76.             else if (flagValue == "3") {  
  77.                 alert("图片上传失败!");  
  78.             }  
  79.             else {  
  80.                 hidPut.value = response;  
  81.                 img.src = g_AjxTempDir + response;  
  82.             }  
  83.         }  
  84.     });  
  85. }  
  86.   
  87. //删除文档  
  88. function DelFile(doc, hidPut) {  
  89.     hidPut.value = "";  
  90.     doc.innerHTML = "<input type=\"text\" disabled=\"disabled\" />";  
  91. }  
  92.   
  93. //删除图片  
  94. function DelImg(img, hidPut) {  
  95.     hidPut.value = "";  
  96.     img.src = "/images/nophoto.gif";  
  97. }  

 

4、创建/Common/UploadHandler.ashx处理程序

[csharp] view plaincopy
 
  1. <%@ WebHandler Language="C#" Class="UploadHandler" %>  
  2.   
  3. using System;  
  4. using System.Web;  
  5. using System.Text.RegularExpressions;  
  6. using System.IO;  
  7.   
  8. public class UploadHandler : IHttpHandler {  
  9.     private string _filedir = "";    //文件目录  
  10.     /// <summary>  
  11.     /// 处理上传文件(1:文件格式不正确、2:文件大小不正确、3:上传失败、文件名称:上传成功)  
  12.     /// </summary>  
  13.     /// <param name="context"></param>  
  14.     public void ProcessRequest (HttpContext context) {  
  15.         _filedir = context.Server.MapPath(@"/file/temp/");  
  16.         try  
  17.         {  
  18.             string result = "3";  
  19.             string fileType = context.Request.QueryString["fileType"]; //获取上传文件类型  
  20.             if (fileType == "file")  
  21.             {  
  22.                 result = UploadFile(context);  //文档上传  
  23.             }  
  24.             else if (fileType == "img")  
  25.             {  
  26.                 result = UploadImg(context);   //图片上传  
  27.             }  
  28.             context.Response.Write(result);  
  29.         }  
  30.         catch  
  31.         {  
  32.             context.Response.Write("3");//3文件上传失败  
  33.         }  
  34.     }  
  35.       
  36.     /// <summary>  
  37.     /// 文档上传  
  38.     /// </summary>  
  39.     /// <param name="context"></param>  
  40.     /// <returns></returns>  
  41.     private string UploadFile(HttpContext context)  
  42.     {  
  43.         int cout = context.Request.Files.Count;  
  44.         if (cout > 0)  
  45.         {  
  46.             HttpPostedFile hpf = context.Request.Files[0];  
  47.             if (hpf != null)  
  48.             {  
  49.                 string fileExt = Path.GetExtension(hpf.FileName).ToLower();  
  50.                 //只能上传文件,过滤不可上传的文件类型    
  51.                 string fileFilt = ".rar|.zip|.pdf|.pdfx|.txt|.csv|.xls|.xlsx|.doc|.docx......";  
  52.                 if (fileFilt.IndexOf(fileExt) <= -1)  
  53.                 {  
  54.                     return "1";  
  55.                 }  
  56.                   
  57.                 //判断文件大小    
  58.                 int length = hpf.ContentLength;  
  59.                 if (length > 2097152)  
  60.                 {  
  61.                     return "2";  
  62.                 }    
  63.                  
  64.                 Random rd = new Random();  
  65.                 DateTime nowTime = DateTime.Now;  
  66.                 string newFileName = nowTime.Year.ToString() + nowTime.Month.ToString() + nowTime.Day.ToString() + nowTime.Hour.ToString() + nowTime.Minute.ToString() + nowTime.Second.ToString() + rd.Next(1000, 1000000) + Path.GetExtension(hpf.FileName);  
  67.                 if (!Directory.Exists(_filedir))  
  68.                 {  
  69.                     Directory.CreateDirectory(_filedir);  
  70.                 }  
  71.                 string fileName = _filedir + newFileName;  
  72.                 hpf.SaveAs(fileName);  
  73.                 return newFileName;  
  74.             }  
  75.   
  76.         }  
  77.         return "3";  
  78.     }  
  79.   
  80.     /// <summary>  
  81.     /// 图片上传  
  82.     /// </summary>  
  83.     /// <param name="context"></param>  
  84.     /// <returns></returns>  
  85.     private string UploadImg(HttpContext context)  
  86.     {  
  87.         int cout = context.Request.Files.Count;  
  88.         if (cout > 0)  
  89.         {  
  90.             HttpPostedFile hpf = context.Request.Files[0];  
  91.             if (hpf != null)  
  92.             {  
  93.                 string fileExt = Path.GetExtension(hpf.FileName).ToLower();  
  94.                 //只能上传文件,过滤不可上传的文件类型    
  95.                 string fileFilt = ".gif|.jpg|.php|.jsp|.jpeg|.png|......";  
  96.                 if (fileFilt.IndexOf(fileExt) <= -1)  
  97.                 {  
  98.                     return "1";  
  99.                 }  
  100.                   
  101.                 //判断文件大小    
  102.                 int length = hpf.ContentLength;  
  103.                 if (length > 204800)  
  104.                 {  
  105.                     return "2";  
  106.                 }  
  107.                   
  108.                 Random rd = new Random();  
  109.                 DateTime nowTime = DateTime.Now;  
  110.                 string newFileName = nowTime.Year.ToString() + nowTime.Month.ToString() + nowTime.Day.ToString() + nowTime.Hour.ToString() + nowTime.Minute.ToString() + nowTime.Second.ToString() + rd.Next(1000, 1000000) + Path.GetExtension(hpf.FileName);  
  111.                 if (!Directory.Exists(_filedir))  
  112.                 {  
  113.                     Directory.CreateDirectory(_filedir);  
  114.                 }  
  115.                 string fileName = _filedir + newFileName;  
  116.                 hpf.SaveAs(fileName);  
  117.                 return newFileName;  
  118.             }  
  119.   
  120.         }  
  121.         return "3";  
  122.     }  
  123.      
  124.     #region IHttpHandler 成员  
  125.   
  126.     public bool IsReusable  
  127.     {  
  128.         get { throw new NotImplementedException(); }  
  129.     }  
  130.  
  131.     #endregion  
  132. }  

附件1:页面CSS样式

[css] view plaincopy
 
  1. /*上传文件*/  
  2. .uploadFile{margin-bottom:10px;}  
  3. /*上传图片*/  
  4. .uploadImg{}  
  5. .uploadImg img{width:102pxheight:64pxborder:1px solid #CCCCCCdisplayblock;}  

附件2:AjaxUpload.js文件

[javascript] view plaincopy
 
  1. /** 
  2.  * AJAX Upload ( http://valums.com/ajax-upload/ )  
  3.  * Copyright (c) Andris Valums 
  4.  * Licensed under the MIT license ( http://valums.com/mit-license/ ) 
  5.  * Thanks to Gary Haran, David Mark, Corey Burns and others for contributions  
  6.  */  
  7. (function () {  
  8.     /* global window */  
  9.     /* jslint browser: true, devel: true, undef: true, nomen: true, bitwise: true, regexp: true, newcap: true, immed: true */  
  10.   
  11.     /** 
  12.      * Wrapper for FireBug's console.log 
  13.      */  
  14.   
  15.     function log() {  
  16.         if (typeof(console) != 'undefined' && typeof(console.log) == 'function') {  
  17.             Array.prototype.unshift.call(arguments, '[Ajax Upload]');  
  18.             console.log(Array.prototype.join.call(arguments, ' '));  
  19.         }  
  20.     }  
  21.   
  22.     /** 
  23.      * Attaches event to a dom element. 
  24.      * @param {Element} el 
  25.      * @param type event name 
  26.      * @param fn callback This refers to the passed element 
  27.      */  
  28.   
  29.     function addEvent(el, type, fn) {  
  30.         if (el.addEventListener) {  
  31.             el.addEventListener(type, fn, false);  
  32.         } else if (el.attachEvent) {  
  33.             el.attachEvent('on' + type, function () {  
  34.                 fn.call(el);  
  35.             });  
  36.         } else {  
  37.             throw new Error('not supported or DOM not loaded');  
  38.         }  
  39.     }  
  40.   
  41.     /** 
  42.      * Attaches resize event to a window, limiting 
  43.      * number of event fired. Fires only when encounteres 
  44.      * delay of 100 after series of events. 
  45.      *  
  46.      * Some browsers fire event multiple times when resizing 
  47.      * http://www.quirksmode.org/dom/events/resize.html 
  48.      *  
  49.      * @param fn callback This refers to the passed element 
  50.      */  
  51.   
  52.     function addResizeEvent(fn) {  
  53.         var timeout;  
  54.   
  55.         addEvent(window, 'resize'function () {  
  56.             if (timeout) {  
  57.                 clearTimeout(timeout);  
  58.             }  
  59.             timeout = setTimeout(fn, 100);  
  60.         });  
  61.     }  
  62.   
  63.     // Needs more testing, will be rewriten for next version          
  64.     // getOffset function copied from jQuery lib (http://jquery.com/)  
  65.     if (document.documentElement.getBoundingClientRect) {  
  66.         // Get Offset using getBoundingClientRect  
  67.         // http://ejohn.org/blog/getboundingclientrect-is-awesome/  
  68.         var getOffset = function (el) {  
  69.             var box = el.getBoundingClientRect();  
  70.             var doc = el.ownerDocument;  
  71.             var body = doc.body;  
  72.             var docElem = doc.documentElement; // for ie   
  73.             var clientTop = docElem.clientTop || body.clientTop || 0;  
  74.             var clientLeft = docElem.clientLeft || body.clientLeft || 0;  
  75.   
  76.             // In Internet Explorer 7 getBoundingClientRect property is treated as physical,  
  77.             // while others are logical. Make all logical, like in IE8.   
  78.             var zoom = 1;  
  79.             if (body.getBoundingClientRect) {  
  80.                 var bound = body.getBoundingClientRect();  
  81.                 zoom = (bound.right - bound.left) / body.clientWidth;  
  82.             }  
  83.   
  84.             if (zoom > 1) {  
  85.                 clientTop = 0;  
  86.                 clientLeft = 0;  
  87.             }  
  88.   
  89.             var top = box.top / zoom + (window.pageYOffset || docElem && docElem.scrollTop / zoom || body.scrollTop / zoom) - clientTop,  
  90.                 left = box.left / zoom + (window.pageXOffset || docElem && docElem.scrollLeft / zoom || body.scrollLeft / zoom) - clientLeft;  
  91.   
  92.             return {  
  93.                 top: top,  
  94.                 left: left  
  95.             };  
  96.         };  
  97.     } else {  
  98.         // Get offset adding all offsets   
  99.         var getOffset = function (el) {  
  100.             var top = 0,  
  101.                 left = 0;  
  102.             do {  
  103.                 top += el.offsetTop || 0;  
  104.                 left += el.offsetLeft || 0;  
  105.                 el = el.offsetParent;  
  106.             } while (el);  
  107.   
  108.             return {  
  109.                 left: left,  
  110.                 top: top  
  111.             };  
  112.         };  
  113.     }  
  114.   
  115.     /** 
  116.      * Returns left, top, right and bottom properties describing the border-box, 
  117.      * in pixels, with the top-left relative to the body 
  118.      * @param {Element} el 
  119.      * @return {Object} Contains left, top, right,bottom 
  120.      */  
  121.   
  122.     function getBox(el) {  
  123.         var left, right, top, bottom;  
  124.         var offset = getOffset(el);  
  125.         left = offset.left;  
  126.         top = offset.top;  
  127.   
  128.         right = left + el.offsetWidth;  
  129.         bottom = top + el.offsetHeight;  
  130.   
  131.         return {  
  132.             left: left,  
  133.             right: right,  
  134.             top: top,  
  135.             bottom: bottom  
  136.         };  
  137.     }  
  138.   
  139.     /** 
  140.      * Helper that takes object literal 
  141.      * and add all properties to element.style 
  142.      * @param {Element} el 
  143.      * @param {Object} styles 
  144.      */  
  145.   
  146.     function addStyles(el, styles) {  
  147.         for (var name in styles) {  
  148.             if (styles.hasOwnProperty(name)) {  
  149.                 el.style[name] = styles[name];  
  150.             }  
  151.         }  
  152.     }  
  153.   
  154.     /** 
  155.      * Function places an absolutely positioned 
  156.      * element on top of the specified element 
  157.      * copying position and dimentions. 
  158.      * @param {Element} from 
  159.      * @param {Element} to 
  160.      */  
  161.   
  162.     function copyLayout(from, to) {  
  163.         var box = getBox(from);  
  164.   
  165.         addStyles(to, {  
  166.             position: 'absolute',  
  167.             left: box.left + 'px',  
  168.             top: box.top + 'px',  
  169.             width: from.offsetWidth + 'px',  
  170.             height: from.offsetHeight + 'px'  
  171.         });  
  172.     }  
  173.   
  174.     /** 
  175.      * Creates and returns element from html chunk 
  176.      * Uses innerHTML to create an element 
  177.      */  
  178.     var toElement = (function () {  
  179.         var div = document.createElement('div');  
  180.         return function (html) {  
  181.             div.innerHTML = html;  
  182.             var el = div.firstChild;  
  183.             return div.removeChild(el);  
  184.         };  
  185.     })();  
  186.   
  187.     /** 
  188.      * Function generates unique id 
  189.      * @return unique id  
  190.      */  
  191.     var getUID = (function () {  
  192.         var id = 0;  
  193.         return function () {  
  194.             return 'ValumsAjaxUpload' + id++;  
  195.         };  
  196.     })();  
  197.   
  198.     /** 
  199.      * Get file name from path 
  200.      * @param {String} file path to file 
  201.      * @return filename 
  202.      */  
  203.   
  204.     function fileFromPath(file) {  
  205.         return file.replace(/.*(\/|\\)/, "");  
  206.     }  
  207.   
  208.     /** 
  209.      * Get file extension lowercase 
  210.      * @param {String} file name 
  211.      * @return file extenstion 
  212.      */  
  213.   
  214.     function getExt(file) {  
  215.         return (-1 !== file.indexOf('.')) ? file.replace(/.*[.]/, '') : '';  
  216.     }  
  217.   
  218.     function hasClass(el, name) {  
  219.         var re = new RegExp('\\b' + name + '\\b');  
  220.         return re.test(el.className);  
  221.     }  
  222.   
  223.     function addClass(el, name) {  
  224.         if (!hasClass(el, name)) {  
  225.             el.className += ' ' + name;  
  226.         }  
  227.     }  
  228.   
  229.     function removeClass(el, name) {  
  230.         var re = new RegExp('\\b' + name + '\\b');  
  231.         el.className = el.className.replace(re, '');  
  232.     }  
  233.   
  234.     function removeNode(el) {  
  235.         el.parentNode.removeChild(el);  
  236.     }  
  237.   
  238.     /** 
  239.      * Easy styling and uploading 
  240.      * @constructor 
  241.      * @param button An element you want convert to  
  242.      * upload button. Tested dimentions up to 500x500px 
  243.      * @param {Object} options See defaults below. 
  244.      */  
  245.     window.AjaxUpload = function (button, options) {  
  246.         this._settings = {  
  247.             // Location of the server-side upload script  
  248.             action: 'upload.php',  
  249.             // File upload name  
  250.             name: 'userfile',  
  251.             // Additional data to send  
  252.             data: {},  
  253.             // Submit file as soon as it's selected  
  254.             autoSubmit: true,  
  255.             // The type of data that you're expecting back from the server.  
  256.             // html and xml are detected automatically.  
  257.             // Only useful when you are using json data as a response.  
  258.             // Set to "json" in that case.   
  259.             responseType: false,  
  260.             // Class applied to button when mouse is hovered  
  261.             hoverClass: 'hover',  
  262.             // Class applied to button when AU is disabled  
  263.             disabledClass: 'disabled',  
  264.             // When user selects a file, useful with autoSubmit disabled  
  265.             // You can return false to cancel upload              
  266.             onChange: function (file, extension) {},  
  267.             // Callback to fire before file is uploaded  
  268.             // You can return false to cancel upload  
  269.             onSubmit: function (file, extension) {},  
  270.             // Fired when file upload is completed  
  271.             // WARNING! DO NOT USE "FALSE" STRING AS A RESPONSE!  
  272.             onComplete: function (file, response) {}  
  273.         };  
  274.   
  275.         // Merge the users options with our defaults  
  276.         for (var i in options) {  
  277.             if (options.hasOwnProperty(i)) {  
  278.                 this._settings[i] = options[i];  
  279.             }  
  280.         }  
  281.   
  282.         // button isn't necessary a dom element  
  283.         if (button.jquery) {  
  284.             // jQuery object was passed  
  285.             button = button[0];  
  286.         } else if (typeof button == "string") {  
  287.             if (/^#.*/.test(button)) {  
  288.                 // If jQuery user passes #elementId don't break it                    
  289.                 button = button.slice(1);  
  290.             }  
  291.   
  292.             button = document.getElementById(button);  
  293.         }  
  294.   
  295.         if (!button || button.nodeType !== 1) {  
  296.             throw new Error("Please make sure that you're passing a valid element");  
  297.         }  
  298.   
  299.         if (button.nodeName.toUpperCase() == 'A') {  
  300.             // disable link                         
  301.             addEvent(button, 'click'function (e) {  
  302.                 if (e && e.preventDefault) {  
  303.                     e.preventDefault();  
  304.                 } else if (window.event) {  
  305.                     window.event.returnValue = false;  
  306.                 }  
  307.             });  
  308.         }  
  309.   
  310.         // DOM element  
  311.         this._button = button;  
  312.         // DOM element                   
  313.         this._input = null;  
  314.         // If disabled clicking on button won't do anything  
  315.         this._disabled = false;  
  316.   
  317.         // if the button was disabled before refresh if will remain  
  318.         // disabled in FireFox, let's fix it  
  319.         this.enable();  
  320.   
  321.         this._rerouteClicks();  
  322.     };  
  323.   
  324.     // assigning methods to our class  
  325.     AjaxUpload.prototype = {  
  326.         setData: function (data) {  
  327.             this._settings.data = data;  
  328.         },  
  329.         disable: function () {  
  330.             addClass(this._button, this._settings.disabledClass);  
  331.             this._disabled = true;  
  332.   
  333.             var nodeName = this._button.nodeName.toUpperCase();  
  334.             if (nodeName == 'INPUT' || nodeName == 'BUTTON') {  
  335.                 this._button.setAttribute('disabled''disabled');  
  336.             }  
  337.   
  338.             // hide input  
  339.             if (this._input) {  
  340.                 // We use visibility instead of display to fix problem with Safari 4  
  341.                 // The problem is that the value of input doesn't change if it   
  342.                 // has display none when user selects a file             
  343.                 this._input.parentNode.style.visibility = 'hidden';  
  344.             }  
  345.         },  
  346.         enable: function () {  
  347.             removeClass(this._button, this._settings.disabledClass);  
  348.             this._button.removeAttribute('disabled');  
  349.             this._disabled = false;  
  350.   
  351.         },  
  352.         /** 
  353.          * Creates invisible file input  
  354.          * that will hover above the button 
  355.          * <div><input type='file' /></div> 
  356.          */  
  357.         _createInput: function () {  
  358.             var self = this;  
  359.   
  360.             var input = document.createElement("input");  
  361.             input.setAttribute('type''file');  
  362.             input.setAttribute('name'this._settings.name);  
  363.   
  364.             addStyles(input, {  
  365.                 'position''absolute',  
  366.                 // in Opera only 'browse' button  
  367.                 // is clickable and it is located at  
  368.                 // the right side of the input  
  369.                 'right': 0,  
  370.                 'margin': 0,  
  371.                 'padding': 0,  
  372.                 'fontSize''480px',  
  373.                 'cursor''pointer'  
  374.             });  
  375.   
  376.             var div = document.createElement("div");  
  377.             addStyles(div, {  
  378.                 'display''block',  
  379.                 'position''absolute',  
  380.                 'overflow''hidden',  
  381.                 'margin': 0,  
  382.                 'padding': 0,  
  383.                 'opacity': 0,  
  384.                 // Make sure browse button is in the right side  
  385.                 // in Internet Explorer  
  386.                 'direction''ltr',  
  387.                 //Max zIndex supported by Opera 9.0-9.2  
  388.                 'zIndex': 2147483583  
  389.             });  
  390.   
  391.             // Make sure that element opacity exists.  
  392.             // Otherwise use IE filter              
  393.             if (div.style.opacity !== "0") {  
  394.                 if (typeof(div.filters) == 'undefined') {  
  395.                     throw new Error('Opacity not supported by the browser');  
  396.                 }  
  397.                 div.style.filter = "alpha(opacity=0)";  
  398.             }  
  399.   
  400.             addEvent(input, 'change'function () {  
  401.   
  402.                 if (!input || input.value === '') {  
  403.                     return;  
  404.                 }  
  405.   
  406.                 // Get filename from input, required                  
  407.                 // as some browsers have path instead of it            
  408.                 var file = fileFromPath(input.value);  
  409.   
  410.                 if (false === self._settings.onChange.call(self, file, getExt(file))) {  
  411.                     self._clearInput();  
  412.                     return;  
  413.                 }  
  414.   
  415.                 // Submit form when value is changed  
  416.                 if (self._settings.autoSubmit) {  
  417.                     self.submit();  
  418.                 }  
  419.             });  
  420.   
  421.             addEvent(input, 'mouseover'function () {  
  422.                 addClass(self._button, self._settings.hoverClass);  
  423.             });  
  424.   
  425.             addEvent(input, 'mouseout'function () {  
  426.                 removeClass(self._button, self._settings.hoverClass);  
  427.   
  428.                 // We use visibility instead of display to fix problem with Safari 4  
  429.                 // The problem is that the value of input doesn't change if it   
  430.                 // has display none when user selects a file             
  431.                 input.parentNode.style.visibility = 'hidden';  
  432.   
  433.             });  
  434.   
  435.             div.appendChild(input);  
  436.             document.body.appendChild(div);  
  437.   
  438.             this._input = input;  
  439.         },  
  440.         _clearInput: function () {  
  441.             if (!this._input) {  
  442.                 return;  
  443.             }  
  444.   
  445.             // this._input.value = ''; Doesn't work in IE6                                 
  446.             removeNode(this._input.parentNode);  
  447.             this._input = null;  
  448.             this._createInput();  
  449.   
  450.             removeClass(this._button, this._settings.hoverClass);  
  451.         },  
  452.         /** 
  453.          * Function makes sure that when user clicks upload button, 
  454.          * the this._input is clicked instead 
  455.          */  
  456.         _rerouteClicks: function () {  
  457.             var self = this;  
  458.   
  459.             // IE will later display 'access denied' error  
  460.             // if you use using self._input.click()  
  461.             // other browsers just ignore click()  
  462.   
  463.             addEvent(self._button, 'mouseover'function () {  
  464.                 if (self._disabled) {  
  465.                     return;  
  466.                 }  
  467.   
  468.                 if (!self._input) {  
  469.                     self._createInput();  
  470.                 }  
  471.   
  472.                 var div = self._input.parentNode;  
  473.                 copyLayout(self._button, div);  
  474.                 div.style.visibility = 'visible';  
  475.   
  476.             });  
  477.   
  478.   
  479.             // commented because we now hide input on mouseleave  
  480.             /** 
  481.              * When the window is resized the elements  
  482.              * can be misaligned if button position depends 
  483.              * on window size 
  484.              */  
  485.             //addResizeEvent(function(){  
  486.             //    if (self._input){  
  487.             //        copyLayout(self._button, self._input.parentNode);  
  488.             //    }  
  489.             //});              
  490.   
  491.         },  
  492.         /** 
  493.          * Creates iframe with unique name 
  494.          * @return {Element} iframe 
  495.          */  
  496.         _createIframe: function () {  
  497.             // We can't use getTime, because it sometimes return  
  498.             // same value in safari :(  
  499.             var id = getUID();  
  500.   
  501.             // We can't use following code as the name attribute  
  502.             // won't be properly registered in IE6, and new window  
  503.             // on form submit will open  
  504.             // var iframe = document.createElement('iframe');  
  505.             // iframe.setAttribute('name', id);                          
  506.   
  507.             var iframe = toElement('<iframe src="javascript:false;" name="' + id + '" />');  
  508.             // src="javascript:false; was added  
  509.             // because it possibly removes ie6 prompt   
  510.             // "This page contains both secure and nonsecure items"  
  511.             // Anyway, it doesn't do any harm.              
  512.             iframe.setAttribute('id', id);  
  513.   
  514.             iframe.style.display = 'none';  
  515.             document.body.appendChild(iframe);  
  516.   
  517.             return iframe;  
  518.         },  
  519.         /** 
  520.          * Creates form, that will be submitted to iframe 
  521.          * @param {Element} iframe Where to submit 
  522.          * @return {Element} form 
  523.          */  
  524.         _createForm: function (iframe) {  
  525.             var settings = this._settings;  
  526.   
  527.             // We can't use the following code in IE6  
  528.             // var form = document.createElement('form');  
  529.             // form.setAttribute('method', 'post');  
  530.             // form.setAttribute('enctype', 'multipart/form-data');  
  531.             // Because in this case file won't be attached to request                      
  532.             var form = toElement('<form method="post" enctype="multipart/form-data"></form>');  
  533.   
  534.             form.setAttribute('action', settings.action);  
  535.             form.setAttribute('target', iframe.name);  
  536.             form.style.display = 'none';  
  537.             document.body.appendChild(form);  
  538.   
  539.             // Create hidden input element for each data key  
  540.             for (var prop in settings.data) {  
  541.                 if (settings.data.hasOwnProperty(prop)) {  
  542.                     var el = document.createElement("input");  
  543.                     el.setAttribute('type''hidden');  
  544.                     el.setAttribute('name', prop);  
  545.                     el.setAttribute('value', settings.data[prop]);  
  546.                     form.appendChild(el);  
  547.                 }  
  548.             }  
  549.             return form;  
  550.         },  
  551.         /** 
  552.          * Gets response from iframe and fires onComplete event when ready 
  553.          * @param iframe 
  554.          * @param file Filename to use in onComplete callback  
  555.          */  
  556.         _getResponse: function (iframe, file) {  
  557.             // getting response  
  558.             var toDeleteFlag = false,  
  559.                 self = this,  
  560.                 settings = this._settings;  
  561.   
  562.             addEvent(iframe, 'load'function () {  
  563.   
  564.                 if ( // For Safari   
  565.                 iframe.src == "javascript:'%3Chtml%3E%3C/html%3E';" ||  
  566.                 // For FF, IE  
  567.                 iframe.src == "javascript:'<html></html>';") {  
  568.                     // First time around, do not delete.  
  569.                     // We reload to blank page, so that reloading main page  
  570.                     // does not re-submit the post.  
  571.   
  572.                     if (toDeleteFlag) {  
  573.                         // Fix busy state in FF3  
  574.                         setTimeout(function () {  
  575.                             removeNode(iframe);  
  576.                         },  
  577.                         0);  
  578.                     }  
  579.   
  580.                     return;  
  581.                 }  
  582.   
  583.                 var doc = iframe.contentDocument ? iframe.contentDocument : window.frames[iframe.id].document;  
  584.   
  585.                 // fixing Opera 9.26,10.00  
  586.                 if (doc.readyState && doc.readyState != 'complete') {  
  587.                     // Opera fires load event multiple times  
  588.                     // Even when the DOM is not ready yet  
  589.                     // this fix should not affect other browsers  
  590.                     return;  
  591.                 }  
  592.   
  593.                 // fixing Opera 9.64  
  594.                 if (doc.body && doc.body.innerHTML == "false") {  
  595.                     // In Opera 9.64 event was fired second time  
  596.                     // when body.innerHTML changed from false   
  597.                     // to server response approx. after 1 sec  
  598.                     return;  
  599.                 }  
  600.   
  601.                 var response;  
  602.   
  603.                 if (doc.XMLDocument) {  
  604.                     // response is a xml document Internet Explorer property  
  605.                     response = doc.XMLDocument;  
  606.                 } else if (doc.body) {  
  607.                     // response is html document or plain text  
  608.                     response = doc.body.innerHTML;  
  609.   
  610.                     if (settings.responseType && settings.responseType.toLowerCase() == 'json') {  
  611.                         // If the document was sent as 'application/javascript' or  
  612.                         // 'text/javascript', then the browser wraps the text in a <pre>  
  613.                         // tag and performs html encoding on the contents.  In this case,  
  614.                         // we need to pull the original text content from the text node's  
  615.                         // nodeValue property to retrieve the unmangled content.  
  616.                         // Note that IE6 only understands text/html  
  617.                         if (doc.body.firstChild && doc.body.firstChild.nodeName.toUpperCase() == 'PRE') {  
  618.                             response = doc.body.firstChild.firstChild.nodeValue;  
  619.                         }  
  620.   
  621.                         if (response) {  
  622.                             response = eval("(" + response + ")");  
  623.                         } else {  
  624.                             response = {};  
  625.                         }  
  626.                     }  
  627.                 } else {  
  628.                     // response is a xml document  
  629.                     response = doc;  
  630.                 }  
  631.   
  632.                 settings.onComplete.call(self, file, response);  
  633.   
  634.                 // Reload blank page, so that reloading main page  
  635.                 // does not re-submit the post. Also, remember to  
  636.                 // delete the frame  
  637.                 toDeleteFlag = true;  
  638.   
  639.                 // Fix IE mixed content issue  
  640.                 iframe.src = "javascript:'<html></html>';";  
  641.             });  
  642.         },  
  643.         /** 
  644.          * Upload file contained in this._input 
  645.          */  
  646.         submit: function () {  
  647.             var self = this,  
  648.                 settings = this._settings;  
  649.   
  650.             if (!this._input || this._input.value === '') {  
  651.                 return;  
  652.             }  
  653.   
  654.             var file = fileFromPath(this._input.value);  
  655.   
  656.             // user returned false to cancel upload  
  657.             if (false === settings.onSubmit.call(this, file, getExt(file))) {  
  658.                 this._clearInput();  
  659.                 return;  
  660.             }  
  661.   
  662.             // sending request      
  663.             var iframe = this._createIframe();  
  664.             var form = this._createForm(iframe);  
  665.   
  666.             // assuming following structure  
  667.             // div -> input type='file'  
  668.             removeNode(this._input.parentNode);  
  669.             removeClass(self._button, self._settings.hoverClass);  
  670.   
  671.             form.appendChild(this._input);  
  672.   
  673.             form.submit();  
  674.   
  675.             // request set, clean up                  
  676.             removeNode(form);  
  677.             form = null;  
  678.             removeNode(this._input);  
  679.             this._input = null;  
  680.   
  681.             // Get response from iframe and fire onComplete event when ready  
  682.             this._getResponse(iframe, file);  
  683.   
  684.             // get ready for next request              
  685.             this._createInput();  
  686.         }  
  687.     };  
  688. })();  

展开阅读全文

没有更多推荐了,返回首页