AjaxUpLoad.js使用实现文件上传

jerry JQuery 2015年09月15日 收藏

AjaxUpLoad.js的使用实现无刷新文件上传,如图。


图1 文件上传前
1351950702_9922[1].png
图2 文件上传后
1351950828_1745[1].png

1、创建页面并编写HTML
上传文档: 

  1.  <div class="uploadFile">  
  2.         <span id="doc"><input type="text" disabled="disabled" /></span>  
  3.         <input type="hidden" id="hidFileName"  />  
  4.         <input type="button" id="btnUploadFile" value="上传" />  
  5.         <input type="button" id="btnDeleteFile" value="删除"  />  
  6.     </div>

上传图片: 

  1. <div class="uploadImg">  
  2.         <img id="imgShow" src="/images/nophoto.gif" />  
  3.         <input type="hidden" id="hidImgName" />  
  4.         <input type="button" id="btnUploadImg" value="上传" />  
  5.         <input type="button" id="btnDeleteImg" value="删除" />  
  6.     </div>

2、引用AjaxUpload.js文件

  1.  <script src="/js/common/AjaxUpload.js" type="text/javascript"></script>

3、编写JS脚本

  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处理程序

  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样式

  1. /*上传文件*/  
  2.     .uploadFile{margin-bottom:10px;}  
  3.     /*上传图片*/  
  4.     .uploadImg{}  
  5.     .uploadImg img{width:102px; height:64px; border:1px solid #CCCCCC; display: block;}

附件2:AjaxUpload.js文件

  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.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.     })();