ajaxupload.js java_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

*/

functionlog() {

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

*/

functionaddEvent(el, type, fn) {

if(el.addEventListener) {

el.addEventListener(type, fn, false);

} elseif(el.attachEvent) {

el.attachEvent('on'+ type, function() {

fn.call(el);

});

} else{

thrownewError('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

*/

functionaddResizeEvent(fn) {

vartimeout;

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/

vargetOffset = function(el) {

varbox = el.getBoundingClientRect();

vardoc = el.ownerDocument;

varbody = doc.body;

vardocElem = doc.documentElement; // for ie

varclientTop = docElem.clientTop || body.clientTop || 0;

varclientLeft = 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.

varzoom = 1;

if(body.getBoundingClientRect) {

varbound = body.getBoundingClientRect();

zoom = (bound.right - bound.left) / body.clientWidth;

}

if(zoom > 1) {

clientTop = 0;

clientLeft = 0;

}

vartop = 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

vargetOffset = function(el) {

vartop = 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

*/

functiongetBox(el) {

varleft, right, top, bottom;

varoffset = 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

*/

functionaddStyles(el, styles) {

for(varname instyles) {

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

*/

functioncopyLayout(from, to) {

varbox = 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

*/

vartoElement = (function() {

vardiv = document.createElement('div');

returnfunction(html) {

div.innerHTML = html;

varel = div.firstChild;

returndiv.removeChild(el);

};

})();

/**

* Function generates unique id

* @return unique id

*/

vargetUID = (function() {

varid = 0;

returnfunction() {

return'ValumsAjaxUpload'+ id++;

};

})();

/**

* Get file name from path

* @param {String} file path to file

* @return filename

*/

functionfileFromPath(file) {

returnfile.replace(/.*(\/|\\)/, "");

}

/**

* Get file extension lowercase

* @param {String} file name

* @return file extenstion

*/

functiongetExt(file) {

return(-1 !== file.indexOf('.')) ? file.replace(/.*[.]/, '') : '';

}

functionhasClass(el, name) {

varre = newRegExp('\\b'+ name + '\\b');

returnre.test(el.className);

}

functionaddClass(el, name) {

if(!hasClass(el, name)) {

el.className += ' '+ name;

}

}

functionremoveClass(el, name) {

varre = newRegExp('\\b'+ name + '\\b');

el.className = el.className.replace(re, '');

}

functionremoveNode(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(vari inoptions) {

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];

} elseif(typeofbutton == "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) {

thrownewError("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();

} elseif(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;

varnodeName = 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

*/

_createInput: function() {

varself = this;

varinput = 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'

});

vardiv = 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') {

thrownewError('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

varfile = 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() {

varself = 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();

}

vardiv = 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 :(

varid = 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);

variframe = toElement('');

// 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);

returniframe;

},

/**

* Creates form, that will be submitted to iframe

* @param {Element} iframe Where to submit

* @return {Element} form

*/

_createForm: function(iframe) {

varsettings = 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

varform = toElement('

');

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(varprop insettings.data) {

if(settings.data.hasOwnProperty(prop)) {

varel = document.createElement("input");

el.setAttribute('type', 'hidden');

el.setAttribute('name', prop);

el.setAttribute('value', settings.data[prop]);

form.appendChild(el);

}

}

returnform;

},

/**

* 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

vartoDeleteFlag = 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:'';") {

// 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;

}

vardoc = 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;

}

varresponse;

if(doc.XMLDocument) {

// response is a xml document Internet Explorer property

response = doc.XMLDocument;

} elseif(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 

 
 

// 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:'';";

});

},

/**

* Upload file contained in this._input

*/

submit: function() {

varself = this,

settings = this._settings;

if(!this._input || this._input.value === '') {

return;

}

varfile = fileFromPath(this._input.value);

// user returned false to cancel upload

if(false=== settings.onSubmit.call(this, file, getExt(file))) {

this._clearInput();

return;

}

// sending request

variframe = this._createIframe();

varform = 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();

}

};

})();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值