首页 > 开发 > AJAX > 正文

AjaxUpLoad.js实现文件上传

2024-09-01 08:33:57
字体:
来源:转载
供稿:网友

AjaxUpload.js文件的代码,供大家参考,具体内容如下

/**  * AJAX Upload ( http://valums.com/ajax-upload/ )  * Copyright (c) Andris Valums  * Licensed under the MIT license ( http://valums.com/mit-license/ )  * Thanks to Gary Haran, David Mark, Corey Burns and others for contributions  */ (function () {  /* global window */  /* jslint browser: true, devel: true, undef: true, nomen: true, bitwise: true, regexp: true, newcap: true, immed: true */   /**   * Wrapper for FireBug's console.log   */   function log() {   if (typeof(console) != 'undefined' && typeof(console.log) == 'function') {    Array.prototype.unshift.call(arguments, '[Ajax Upload]');    console.log(Array.prototype.join.call(arguments, ' '));   }  }   /**   * Attaches event to a dom element.   * @param {Element} el   * @param type event name   * @param fn callback This refers to the passed element   */   function addEvent(el, type, fn) {   if (el.addEventListener) {    el.addEventListener(type, fn, false);   } else if (el.attachEvent) {    el.attachEvent('on' + type, function () {     fn.call(el);    });   } else {    throw new Error('not supported or DOM not loaded');   }  }   /**   * Attaches resize event to a window, limiting   * number of event fired. Fires only when encounteres   * delay of 100 after series of events.   *   * Some browsers fire event multiple times when resizing   * http://www.quirksmode.org/dom/events/resize.html   *   * @param fn callback This refers to the passed element   */   function addResizeEvent(fn) {   var timeout;    addEvent(window, 'resize', function () {    if (timeout) {     clearTimeout(timeout);    }    timeout = setTimeout(fn, 100);   });  }   // Needs more testing, will be rewriten for next version    // getOffset function copied from jQuery lib (http://jquery.com/)  if (document.documentElement.getBoundingClientRect) {   // Get Offset using getBoundingClientRect   // http://ejohn.org/blog/getboundingclientrect-is-awesome/   var getOffset = function (el) {    var box = el.getBoundingClientRect();    var doc = el.ownerDocument;    var body = doc.body;    var docElem = doc.documentElement; // for ie    var clientTop = docElem.clientTop || body.clientTop || 0;    var clientLeft = docElem.clientLeft || body.clientLeft || 0;     // In Internet Explorer 7 getBoundingClientRect property is treated as physical,    // while others are logical. Make all logical, like in IE8.    var zoom = 1;    if (body.getBoundingClientRect) {     var bound = body.getBoundingClientRect();     zoom = (bound.right - bound.left) / body.clientWidth;    }     if (zoom > 1) {     clientTop = 0;     clientLeft = 0;    }     var top = box.top / zoom + (window.pageYOffset || docElem && docElem.scrollTop / zoom || body.scrollTop / zoom) - clientTop,     left = box.left / zoom + (window.pageXOffset || docElem && docElem.scrollLeft / zoom || body.scrollLeft / zoom) - clientLeft;     return {     top: top,     left: left    };   };  } else {   // Get offset adding all offsets   var getOffset = function (el) {    var top = 0,     left = 0;    do {     top += el.offsetTop || 0;     left += el.offsetLeft || 0;     el = el.offsetParent;    } while (el);     return {     left: left,     top: top    };   };  }   /**   * Returns left, top, right and bottom properties describing the border-box,   * in pixels, with the top-left relative to the body   * @param {Element} el   * @return {Object} Contains left, top, right,bottom   */   function getBox(el) {   var left, right, top, bottom;   var offset = getOffset(el);   left = offset.left;   top = offset.top;    right = left + el.offsetWidth;   bottom = top + el.offsetHeight;    return {    left: left,    right: right,    top: top,    bottom: bottom   };  }   /**   * Helper that takes object literal   * and add all properties to element.style   * @param {Element} el   * @param {Object} styles   */   function addStyles(el, styles) {   for (var name in styles) {    if (styles.hasOwnProperty(name)) {     el.style[name] = styles[name];    }   }  }   /**   * Function places an absolutely positioned   * element on top of the specified element   * copying position and dimentions.   * @param {Element} from   * @param {Element} to   */   function copyLayout(from, to) {   var box = getBox(from);    addStyles(to, {    position: 'absolute',    left: box.left + 'px',    top: box.top + 'px',    width: from.offsetWidth + 'px',    height: from.offsetHeight + 'px'   });  }   /**   * Creates and returns element from html chunk   * Uses innerHTML to create an element   */  var toElement = (function () {   var div = document.createElement('div');   return function (html) {    div.innerHTML = html;    var el = div.firstChild;    return div.removeChild(el);   };  })();   /**   * Function generates unique id   * @return unique id   */  var getUID = (function () {   var id = 0;   return function () {    return 'ValumsAjaxUpload' + id++;   };  })();   /**   * Get file name from path   * @param {String} file path to file   * @return filename   */   function fileFromPath(file) {   return file.replace(/.*(//|//)/, "");  }   /**   * Get file extension lowercase   * @param {String} file name   * @return file extenstion   */   function getExt(file) {   return (-1 !== file.indexOf('.')) ? file.replace(/.*[.]/, '') : '';  }   function hasClass(el, name) {   var re = new RegExp('//b' + name + '//b');   return re.test(el.className);  }   function addClass(el, name) {   if (!hasClass(el, name)) {    el.className += ' ' + name;   }  }   function removeClass(el, name) {   var re = new RegExp('//b' + name + '//b');   el.className = el.className.replace(re, '');  }   function removeNode(el) {   el.parentNode.removeChild(el);  }   /**   * Easy styling and uploading   * @constructor   * @param button An element you want convert to   * upload button. Tested dimentions up to 500x500px   * @param {Object} options See defaults below.   */  window.AjaxUpload = function (button, options) {   this._settings = {    // Location of the server-side upload script    action: 'upload.php',    // File upload name    name: 'userfile',    // Additional data to send    data: {},    // Submit file as soon as it's selected    autoSubmit: true,    // The type of data that you're expecting back from the server.    // html and xml are detected automatically.    // Only useful when you are using json data as a response.    // Set to "json" in that case.    responseType: false,    // Class applied to button when mouse is hovered    hoverClass: 'hover',    // Class applied to button when AU is disabled    disabledClass: 'disabled',    // When user selects a file, useful with autoSubmit disabled    // You can return false to cancel upload       onChange: function (file, extension) {},    // Callback to fire before file is uploaded    // You can return false to cancel upload    onSubmit: function (file, extension) {},    // Fired when file upload is completed    // WARNING! DO NOT USE "FALSE" STRING AS A RESPONSE!    onComplete: function (file, response) {}   };    // Merge the users options with our defaults   for (var i in options) {    if (options.hasOwnProperty(i)) {     this._settings[i] = options[i];    }   }    // button isn't necessary a dom element   if (button.jquery) {    // jQuery object was passed    button = button[0];   } else if (typeof button == "string") {    if (/^#.*/.test(button)) {     // If jQuery user passes #elementId don't break it         button = button.slice(1);    }     button = document.getElementById(button);   }    if (!button || button.nodeType !== 1) {    throw new Error("Please make sure that you're passing a valid element");   }    if (button.nodeName.toUpperCase() == 'A') {    // disable link          addEvent(button, 'click', function (e) {     if (e && e.preventDefault) {      e.preventDefault();     } else if (window.event) {      window.event.returnValue = false;     }    });   }    // DOM element   this._button = button;   // DOM element       this._input = null;   // If disabled clicking on button won't do anything   this._disabled = false;    // if the button was disabled before refresh if will remain   // disabled in FireFox, let's fix it   this.enable();    this._rerouteClicks();  };   // assigning methods to our class  AjaxUpload.prototype = {   setData: function (data) {    this._settings.data = data;   },   disable: function () {    addClass(this._button, this._settings.disabledClass);    this._disabled = true;     var nodeName = this._button.nodeName.toUpperCase();    if (nodeName == 'INPUT' || nodeName == 'BUTTON') {     this._button.setAttribute('disabled', 'disabled');    }     // hide input    if (this._input) {     // We use visibility instead of display to fix problem with Safari 4     // The problem is that the value of input doesn't change if it     // has display none when user selects a file        this._input.parentNode.style.visibility = 'hidden';    }   },   enable: function () {    removeClass(this._button, this._settings.disabledClass);    this._button.removeAttribute('disabled');    this._disabled = false;    },   /**    * Creates invisible file input    * that will hover above the button    * <div><input type='file' /></div>    */   _createInput: function () {    var self = this;     var input = document.createElement("input");    input.setAttribute('type', 'file');    input.setAttribute('name', this._settings.name);     addStyles(input, {     'position': 'absolute',     // in Opera only 'browse' button     // is clickable and it is located at     // the right side of the input     'right': 0,     'margin': 0,     'padding': 0,     'fontSize': '480px',     'cursor': 'pointer'    });     var div = document.createElement("div");    addStyles(div, {     'display': 'block',     'position': 'absolute',     'overflow': 'hidden',     'margin': 0,     'padding': 0,     'opacity': 0,     // Make sure browse button is in the right side     // in Internet Explorer     'direction': 'ltr',     //Max zIndex supported by Opera 9.0-9.2     'zIndex': 2147483583    });     // Make sure that element opacity exists.    // Otherwise use IE filter       if (div.style.opacity !== "0") {     if (typeof(div.filters) == 'undefined') {      throw new Error('Opacity not supported by the browser');     }     div.style.filter = "alpha(opacity=0)";    }     addEvent(input, 'change', function () {      if (!input || input.value === '') {      return;     }      // Get filename from input, required         // as some browsers have path instead of it       var file = fileFromPath(input.value);      if (false === self._settings.onChange.call(self, file, getExt(file))) {      self._clearInput();      return;     }      // Submit form when value is changed     if (self._settings.autoSubmit) {      self.submit();     }    });     addEvent(input, 'mouseover', function () {     addClass(self._button, self._settings.hoverClass);    });     addEvent(input, 'mouseout', function () {     removeClass(self._button, self._settings.hoverClass);      // We use visibility instead of display to fix problem with Safari 4     // The problem is that the value of input doesn't change if it     // has display none when user selects a file        input.parentNode.style.visibility = 'hidden';     });     div.appendChild(input);    document.body.appendChild(div);     this._input = input;   },   _clearInput: function () {    if (!this._input) {     return;    }     // this._input.value = ''; Doesn't work in IE6            removeNode(this._input.parentNode);    this._input = null;    this._createInput();     removeClass(this._button, this._settings.hoverClass);   },   /**    * Function makes sure that when user clicks upload button,    * the this._input is clicked instead    */   _rerouteClicks: function () {    var self = this;     // IE will later display 'access denied' error    // if you use using self._input.click()    // other browsers just ignore click()     addEvent(self._button, 'mouseover', function () {     if (self._disabled) {      return;     }      if (!self._input) {      self._createInput();     }      var div = self._input.parentNode;     copyLayout(self._button, div);     div.style.visibility = 'visible';     });      // commented because we now hide input on mouseleave    /**     * When the window is resized the elements     * can be misaligned if button position depends     * on window size     */    //addResizeEvent(function(){    // if (self._input){    //  copyLayout(self._button, self._input.parentNode);    // }    //});       },   /**    * Creates iframe with unique name    * @return {Element} iframe    */   _createIframe: function () {    // We can't use getTime, because it sometimes return    // same value in safari :(    var id = getUID();     // We can't use following code as the name attribute    // won't be properly registered in IE6, and new window    // on form submit will open    // var iframe = document.createElement('iframe');    // iframe.setAttribute('name', id);           var iframe = toElement('<iframe src="javascript:false;" name="' + id + '" />');    // src="javascript:false; was added    // because it possibly removes ie6 prompt    // "This page contains both secure and nonsecure items"    // Anyway, it doesn't do any harm.       iframe.setAttribute('id', id);     iframe.style.display = 'none';    document.body.appendChild(iframe);     return iframe;   },   /**    * Creates form, that will be submitted to iframe    * @param {Element} iframe Where to submit    * @return {Element} form    */   _createForm: function (iframe) {    var settings = this._settings;     // We can't use the following code in IE6    // var form = document.createElement('form');    // form.setAttribute('method', 'post');    // form.setAttribute('enctype', 'multipart/form-data');    // Because in this case file won't be attached to request         var form = toElement('<form method="post" enctype="multipart/form-data"></form>');     form.setAttribute('action', settings.action);    form.setAttribute('target', iframe.name);    form.style.display = 'none';    document.body.appendChild(form);     // Create hidden input element for each data key    for (var prop in settings.data) {     if (settings.data.hasOwnProperty(prop)) {      var el = document.createElement("input");      el.setAttribute('type', 'hidden');      el.setAttribute('name', prop);      el.setAttribute('value', settings.data[prop]);      form.appendChild(el);     }    }    return form;   },   /**    * Gets response from iframe and fires onComplete event when ready    * @param iframe    * @param file Filename to use in onComplete callback    */   _getResponse: function (iframe, file) {    // getting response    var toDeleteFlag = false,     self = this,     settings = this._settings;     addEvent(iframe, 'load', function () {      if ( // For Safari     iframe.src == "javascript:'%3Chtml%3E%3C/html%3E';" ||     // For FF, IE     iframe.src == "javascript:'<html></html>';") {      // First time around, do not delete.      // We reload to blank page, so that reloading main page      // does not re-submit the post.       if (toDeleteFlag) {       // Fix busy state in FF3       setTimeout(function () {        removeNode(iframe);       },       0);      }       return;     }      var doc = iframe.contentDocument ? iframe.contentDocument : window.frames[iframe.id].document;      // fixing Opera 9.26,10.00     if (doc.readyState && doc.readyState != 'complete') {      // Opera fires load event multiple times      // Even when the DOM is not ready yet      // this fix should not affect other browsers      return;     }      // fixing Opera 9.64     if (doc.body && doc.body.innerHTML == "false") {      // In Opera 9.64 event was fired second time      // when body.innerHTML changed from false      // to server response approx. after 1 sec      return;     }      var response;      if (doc.XMLDocument) {      // response is a xml document Internet Explorer property      response = doc.XMLDocument;     } else if (doc.body) {      // response is html document or plain text      response = doc.body.innerHTML;       if (settings.responseType && settings.responseType.toLowerCase() == 'json') {       // If the document was sent as 'application/javascript' or       // 'text/javascript', then the browser wraps the text in a <pre>       // tag and performs html encoding on the contents. In this case,       // we need to pull the original text content from the text node's       // nodeValue property to retrieve the unmangled content.       // Note that IE6 only understands text/html       if (doc.body.firstChild && doc.body.firstChild.nodeName.toUpperCase() == 'PRE') {        response = doc.body.firstChild.firstChild.nodeValue;       }        if (response) {        response = eval("(" + response + ")");       } else {        response = {};       }      }     } else {      // response is a xml document      response = doc;     }      settings.onComplete.call(self, file, response);      // Reload blank page, so that reloading main page     // does not re-submit the post. Also, remember to     // delete the frame     toDeleteFlag = true;      // Fix IE mixed content issue     iframe.src = "javascript:'<html></html>';";    });   },   /**    * Upload file contained in this._input    */   submit: function () {    var self = this,     settings = this._settings;     if (!this._input || this._input.value === '') {     return;    }     var file = fileFromPath(this._input.value);     // user returned false to cancel upload    if (false === settings.onSubmit.call(this, file, getExt(file))) {     this._clearInput();     return;    }     // sending request     var iframe = this._createIframe();    var form = this._createForm(iframe);     // assuming following structure    // div -> input type='file'    removeNode(this._input.parentNode);    removeClass(self._button, self._settings.hoverClass);     form.appendChild(this._input);     form.submit();     // request set, clean up        removeNode(form);    form = null;    removeNode(this._input);    this._input = null;     // Get response from iframe and fire onComplete event when ready    this._getResponse(iframe, file);     // get ready for next request       this._createInput();   }  }; })(); 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VeVb武林网。


注:相关教程知识阅读请移步到JavaScript/Ajax教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表