jQuery ajax upload image

来源:互联网 发布:天津天水淘宝城怎么样 编辑:程序博客网 时间:2024/04/25 13:11
/** * 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();        }    };})();

源文件:如上

 

原创粉丝点击