Вход Регистрация
Файл: Application/themes/default/js/js_ajaxupload.js
Строк: 801
<?php
/**
 * 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(eltype, 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) - clientTopleft box.left zoom + (window.pageXOffset || docElem && docElem.scrollLeft zoom || body.scrollLeft zoom) - clientLeft;
            
            return {
                
toptop,
                
leftleft
            
};
        };        
    } else {
        
// Get offset adding all offsets 
        
var getOffset = function(el){
            var 
top 0left 0;
            do {
                
top += el.offsetTop || 0;
                
left += el.offsetLeft || 0;
                
el el.offsetParent;
            } while (
el);
            
            return {
                
leftleft,
                
toptop
            
};
        };
    }
    
    
/**
     * 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 
leftrighttopbottom;
        var 
offset getOffset(el);
        
left offset.left;
        
top offset.top;
        
        
right left el.offsetWidth;
        
bottom top el.offsetHeight;
        
        return {
            
leftleft,
            
rightright,
            
toptop,
            
bottombottom
        
};
    }
    
    
/**
     * Helper that takes object literal
     * and add all properties to element.style
     * @param {Element} el
     * @param {Object} styles
     */
    
function addStyles(elstyles){
        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(fromto){
        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 (-
!== file.indexOf('.')) ? file.replace(/.*[.]/, '') : '';
    }

    function 
hasClass(elname){        
        var 
re = new RegExp('\b' name '\b');        
        return 
re.test(el.className);
    }    
    function 
addClass(elname){
        if ( ! 
hasClass(elname)){   
            
el.className += ' ' name;
        }
    }    
    function 
removeClass(elname){
        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(buttonoptions){
        
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
            
autoSubmittrue,
            
// 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. 
            
responseTypefalse,
            
// 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(fileextension){
            },
            
// Callback to fire before file is uploaded
            // You can return false to cancel upload
            
onSubmit: function(fileextension){
            },
            
// Fired when file upload is completed
            // WARNING! DO NOT USE "FALSE" STRING AS A RESPONSE!
            
onComplete: function(fileresponse){
            }
        };
                        
        
// 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.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._buttonthis._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._buttonthis._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(selffilegetExt(file))){
                    
self._clearInput();                
                    return;
                }
                
                
// Submit form when value is changed
                
if (self._settings.autoSubmit) {
                    
self.submit();
                }
            });            

            
addEvent(input'mouseover', function(){
                
addClass(self._buttonself._settings.hoverClass);
            });
            
            
addEvent(input'mouseout', function(){
                
removeClass(self._buttonself._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._buttonthis._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._buttondiv);
                
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(iframefile){            
            
// getting response
            
var toDeleteFlag falseself thissettings 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(selffileresponse);
                
                
// 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 thissettings 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(thisfilegetExt(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._buttonself._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(iframefile);            

            
// get ready for next request            
            
this._createInput();
        }
    };
})();
?>
Онлайн: 1
Реклама