You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					4249 lines
				
				100 KiB
			
		
		
			
		
	
	
					4249 lines
				
				100 KiB
			| 
								 
											2 years ago
										 
									 | 
							
								/*! FileAPI 2.0.7 - BSD | git://github.com/mailru/FileAPI.git
							 | 
						||
| 
								 | 
							
								 * FileAPI — a set of  javascript tools for working with files. Multiupload, drag'n'drop and chunked file upload. Images: crop, resize and auto orientation by EXIF.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * JavaScript Canvas to Blob 2.0.5
							 | 
						||
| 
								 | 
							
								 * https://github.com/blueimp/JavaScript-Canvas-to-Blob
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Copyright 2012, Sebastian Tschan
							 | 
						||
| 
								 | 
							
								 * https://blueimp.net
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Licensed under the MIT license:
							 | 
						||
| 
								 | 
							
								 * http://www.opensource.org/licenses/MIT
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Based on stackoverflow user Stoive's code snippet:
							 | 
						||
| 
								 | 
							
								 * http://stackoverflow.com/q/4998908
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*jslint nomen: true, regexp: true */
							 | 
						||
| 
								 | 
							
								/*global window, atob, Blob, ArrayBuffer, Uint8Array */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(function (window) {
							 | 
						||
| 
								 | 
							
								    'use strict';
							 | 
						||
| 
								 | 
							
								    var CanvasPrototype = window.HTMLCanvasElement &&
							 | 
						||
| 
								 | 
							
								            window.HTMLCanvasElement.prototype,
							 | 
						||
| 
								 | 
							
								        hasBlobConstructor = window.Blob && (function () {
							 | 
						||
| 
								 | 
							
								            try {
							 | 
						||
| 
								 | 
							
								                return Boolean(new Blob());
							 | 
						||
| 
								 | 
							
								            } catch (e) {
							 | 
						||
| 
								 | 
							
								                return false;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }()),
							 | 
						||
| 
								 | 
							
								        hasArrayBufferViewSupport = hasBlobConstructor && window.Uint8Array &&
							 | 
						||
| 
								 | 
							
								            (function () {
							 | 
						||
| 
								 | 
							
								                try {
							 | 
						||
| 
								 | 
							
								                    return new Blob([new Uint8Array(100)]).size === 100;
							 | 
						||
| 
								 | 
							
								                } catch (e) {
							 | 
						||
| 
								 | 
							
								                    return false;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }()),
							 | 
						||
| 
								 | 
							
								        BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder ||
							 | 
						||
| 
								 | 
							
								            window.MozBlobBuilder || window.MSBlobBuilder,
							 | 
						||
| 
								 | 
							
								        dataURLtoBlob = (hasBlobConstructor || BlobBuilder) && window.atob &&
							 | 
						||
| 
								 | 
							
								            window.ArrayBuffer && window.Uint8Array && function (dataURI) {
							 | 
						||
| 
								 | 
							
								                var byteString,
							 | 
						||
| 
								 | 
							
								                    arrayBuffer,
							 | 
						||
| 
								 | 
							
								                    intArray,
							 | 
						||
| 
								 | 
							
								                    i,
							 | 
						||
| 
								 | 
							
								                    mimeString,
							 | 
						||
| 
								 | 
							
								                    bb;
							 | 
						||
| 
								 | 
							
								                if (dataURI.split(',')[0].indexOf('base64') >= 0) {
							 | 
						||
| 
								 | 
							
								                    // Convert base64 to raw binary data held in a string:
							 | 
						||
| 
								 | 
							
								                    byteString = atob(dataURI.split(',')[1]);
							 | 
						||
| 
								 | 
							
								                } else {
							 | 
						||
| 
								 | 
							
								                    // Convert base64/URLEncoded data component to raw binary data:
							 | 
						||
| 
								 | 
							
								                    byteString = decodeURIComponent(dataURI.split(',')[1]);
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                // Write the bytes of the string to an ArrayBuffer:
							 | 
						||
| 
								 | 
							
								                arrayBuffer = new ArrayBuffer(byteString.length);
							 | 
						||
| 
								 | 
							
								                intArray = new Uint8Array(arrayBuffer);
							 | 
						||
| 
								 | 
							
								                for (i = 0; i < byteString.length; i += 1) {
							 | 
						||
| 
								 | 
							
								                    intArray[i] = byteString.charCodeAt(i);
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                // Separate out the mime component:
							 | 
						||
| 
								 | 
							
								                mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
							 | 
						||
| 
								 | 
							
								                // Write the ArrayBuffer (or ArrayBufferView) to a blob:
							 | 
						||
| 
								 | 
							
								                if (hasBlobConstructor) {
							 | 
						||
| 
								 | 
							
								                    return new Blob(
							 | 
						||
| 
								 | 
							
								                        [hasArrayBufferViewSupport ? intArray : arrayBuffer],
							 | 
						||
| 
								 | 
							
								                        {type: mimeString}
							 | 
						||
| 
								 | 
							
								                    );
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                bb = new BlobBuilder();
							 | 
						||
| 
								 | 
							
								                bb.append(arrayBuffer);
							 | 
						||
| 
								 | 
							
								                return bb.getBlob(mimeString);
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								    if (window.HTMLCanvasElement && !CanvasPrototype.toBlob) {
							 | 
						||
| 
								 | 
							
								        if (CanvasPrototype.mozGetAsFile) {
							 | 
						||
| 
								 | 
							
								            CanvasPrototype.toBlob = function (callback, type, quality) {
							 | 
						||
| 
								 | 
							
								                if (quality && CanvasPrototype.toDataURL && dataURLtoBlob) {
							 | 
						||
| 
								 | 
							
								                    callback(dataURLtoBlob(this.toDataURL(type, quality)));
							 | 
						||
| 
								 | 
							
								                } else {
							 | 
						||
| 
								 | 
							
								                    callback(this.mozGetAsFile('blob', type));
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								        } else if (CanvasPrototype.toDataURL && dataURLtoBlob) {
							 | 
						||
| 
								 | 
							
								            CanvasPrototype.toBlob = function (callback, type, quality) {
							 | 
						||
| 
								 | 
							
								                callback(dataURLtoBlob(this.toDataURL(type, quality)));
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    window.dataURLtoBlob = dataURLtoBlob;
							 | 
						||
| 
								 | 
							
								})(window);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*jslint evil: true */
							 | 
						||
| 
								 | 
							
								/*global window, URL, webkitURL, ActiveXObject */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(function (window, undef){
							 | 
						||
| 
								 | 
							
									'use strict';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									var
							 | 
						||
| 
								 | 
							
										gid = 1,
							 | 
						||
| 
								 | 
							
										noop = function (){},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										document = window.document,
							 | 
						||
| 
								 | 
							
										doctype = document.doctype || {},
							 | 
						||
| 
								 | 
							
										userAgent = window.navigator.userAgent,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// https://github.com/blueimp/JavaScript-Load-Image/blob/master/load-image.js#L48
							 | 
						||
| 
								 | 
							
										apiURL = (window.createObjectURL && window) || (window.URL && URL.revokeObjectURL && URL) || (window.webkitURL && webkitURL),
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										Blob = window.Blob,
							 | 
						||
| 
								 | 
							
										File = window.File,
							 | 
						||
| 
								 | 
							
										FileReader = window.FileReader,
							 | 
						||
| 
								 | 
							
										FormData = window.FormData,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										XMLHttpRequest = window.XMLHttpRequest,
							 | 
						||
| 
								 | 
							
										jQuery = window.jQuery,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										html5 =    !!(File && (FileReader && (window.Uint8Array || FormData || XMLHttpRequest.prototype.sendAsBinary)))
							 | 
						||
| 
								 | 
							
												&& !(/safari\//i.test(userAgent) && !/chrome\//i.test(userAgent) && /windows/i.test(userAgent)), // BugFix: https://github.com/mailru/FileAPI/issues/25
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										cors = html5 && ('withCredentials' in (new XMLHttpRequest)),
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										chunked = html5 && !!Blob && !!(Blob.prototype.webkitSlice || Blob.prototype.mozSlice || Blob.prototype.slice),
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// https://github.com/blueimp/JavaScript-Canvas-to-Blob
							 | 
						||
| 
								 | 
							
										dataURLtoBlob = window.dataURLtoBlob,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										_rimg = /img/i,
							 | 
						||
| 
								 | 
							
										_rcanvas = /canvas/i,
							 | 
						||
| 
								 | 
							
										_rimgcanvas = /img|canvas/i,
							 | 
						||
| 
								 | 
							
										_rinput = /input/i,
							 | 
						||
| 
								 | 
							
										_rdata = /^data:[^,]+,/,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										_toString = {}.toString,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										Math = window.Math,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										_SIZE_CONST = function (pow){
							 | 
						||
| 
								 | 
							
											pow = new window.Number(Math.pow(1024, pow));
							 | 
						||
| 
								 | 
							
											pow.from = function (sz){ return Math.round(sz * this); };
							 | 
						||
| 
								 | 
							
											return	pow;
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										_elEvents = {}, // element event listeners
							 | 
						||
| 
								 | 
							
										_infoReader = [], // list of file info processors
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										_readerEvents = 'abort progress error load loadend',
							 | 
						||
| 
								 | 
							
										_xhrPropsExport = 'status statusText readyState response responseXML responseText responseBody'.split(' '),
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										currentTarget = 'currentTarget', // for minimize
							 | 
						||
| 
								 | 
							
										preventDefault = 'preventDefault', // and this too
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										_isArray = function (ar) {
							 | 
						||
| 
								 | 
							
											return	ar && ('length' in ar);
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/**
							 | 
						||
| 
								 | 
							
										 * Iterate over a object or array
							 | 
						||
| 
								 | 
							
										 */
							 | 
						||
| 
								 | 
							
										_each = function (obj, fn, ctx){
							 | 
						||
| 
								 | 
							
											if( obj ){
							 | 
						||
| 
								 | 
							
												if( _isArray(obj) ){
							 | 
						||
| 
								 | 
							
													for( var i = 0, n = obj.length; i < n; i++ ){
							 | 
						||
| 
								 | 
							
														if( i in obj ){
							 | 
						||
| 
								 | 
							
															fn.call(ctx, obj[i], i, obj);
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else {
							 | 
						||
| 
								 | 
							
													for( var key in obj ){
							 | 
						||
| 
								 | 
							
														if( obj.hasOwnProperty(key) ){
							 | 
						||
| 
								 | 
							
															fn.call(ctx, obj[key], key, obj);
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/**
							 | 
						||
| 
								 | 
							
										 * Merge the contents of two or more objects together into the first object
							 | 
						||
| 
								 | 
							
										 */
							 | 
						||
| 
								 | 
							
										_extend = function (dst){
							 | 
						||
| 
								 | 
							
											var args = arguments, i = 1, _ext = function (val, key){ dst[key] = val; };
							 | 
						||
| 
								 | 
							
											for( ; i < args.length; i++ ){
							 | 
						||
| 
								 | 
							
												_each(args[i], _ext);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											return  dst;
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/**
							 | 
						||
| 
								 | 
							
										 * Add event listener
							 | 
						||
| 
								 | 
							
										 */
							 | 
						||
| 
								 | 
							
										_on = function (el, type, fn){
							 | 
						||
| 
								 | 
							
											if( el ){
							 | 
						||
| 
								 | 
							
												var uid = api.uid(el);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( !_elEvents[uid] ){
							 | 
						||
| 
								 | 
							
													_elEvents[uid] = {};
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												var isFileReader = (FileReader && el) && (el instanceof FileReader);
							 | 
						||
| 
								 | 
							
												_each(type.split(/\s+/), function (type){
							 | 
						||
| 
								 | 
							
													if( jQuery && !isFileReader){
							 | 
						||
| 
								 | 
							
														jQuery.event.add(el, type, fn);
							 | 
						||
| 
								 | 
							
													} else {
							 | 
						||
| 
								 | 
							
														if( !_elEvents[uid][type] ){
							 | 
						||
| 
								 | 
							
															_elEvents[uid][type] = [];
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														_elEvents[uid][type].push(fn);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														if( el.addEventListener ){ el.addEventListener(type, fn, false); }
							 | 
						||
| 
								 | 
							
														else if( el.attachEvent ){ el.attachEvent('on'+type, fn); }
							 | 
						||
| 
								 | 
							
														else { el['on'+type] = fn; }
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												});
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/**
							 | 
						||
| 
								 | 
							
										 * Remove event listener
							 | 
						||
| 
								 | 
							
										 */
							 | 
						||
| 
								 | 
							
										_off = function (el, type, fn){
							 | 
						||
| 
								 | 
							
											if( el ){
							 | 
						||
| 
								 | 
							
												var uid = api.uid(el), events = _elEvents[uid] || {};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												var isFileReader = (FileReader && el) && (el instanceof FileReader);
							 | 
						||
| 
								 | 
							
												_each(type.split(/\s+/), function (type){
							 | 
						||
| 
								 | 
							
													if( jQuery && !isFileReader){
							 | 
						||
| 
								 | 
							
														jQuery.event.remove(el, type, fn);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													else {
							 | 
						||
| 
								 | 
							
														var fns = events[type] || [], i = fns.length;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														while( i-- ){
							 | 
						||
| 
								 | 
							
															if( fns[i] === fn ){
							 | 
						||
| 
								 | 
							
																fns.splice(i, 1);
							 | 
						||
| 
								 | 
							
																break;
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														if( el.addEventListener ){ el.removeEventListener(type, fn, false); }
							 | 
						||
| 
								 | 
							
														else if( el.detachEvent ){ el.detachEvent('on'+type, fn); }
							 | 
						||
| 
								 | 
							
														else { el['on'+type] = null; }
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												});
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										_one = function(el, type, fn){
							 | 
						||
| 
								 | 
							
											_on(el, type, function _(evt){
							 | 
						||
| 
								 | 
							
												_off(el, type, _);
							 | 
						||
| 
								 | 
							
												fn(evt);
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										_fixEvent = function (evt){
							 | 
						||
| 
								 | 
							
											if( !evt.target ){ evt.target = window.event && window.event.srcElement || document; }
							 | 
						||
| 
								 | 
							
											if( evt.target.nodeType === 3 ){ evt.target = evt.target.parentNode; }
							 | 
						||
| 
								 | 
							
											return  evt;
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										_supportInputAttr = function (attr){
							 | 
						||
| 
								 | 
							
											var input = document.createElement('input');
							 | 
						||
| 
								 | 
							
											input.setAttribute('type', "file");
							 | 
						||
| 
								 | 
							
											return attr in input;
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/**
							 | 
						||
| 
								 | 
							
										 * FileAPI (core object)
							 | 
						||
| 
								 | 
							
										 */
							 | 
						||
| 
								 | 
							
										api = {
							 | 
						||
| 
								 | 
							
											version: '2.0.7',
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											cors: false,
							 | 
						||
| 
								 | 
							
											html5: true,
							 | 
						||
| 
								 | 
							
											media: false,
							 | 
						||
| 
								 | 
							
											formData: true,
							 | 
						||
| 
								 | 
							
											multiPassResize: true,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											debug: false,
							 | 
						||
| 
								 | 
							
											pingUrl: false,
							 | 
						||
| 
								 | 
							
											multiFlash: false,
							 | 
						||
| 
								 | 
							
											flashAbortTimeout: 0,
							 | 
						||
| 
								 | 
							
											withCredentials: true,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											staticPath: './dist/',
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											flashUrl: 0, // @default: './FileAPI.flash.swf'
							 | 
						||
| 
								 | 
							
											flashImageUrl: 0, // @default: './FileAPI.flash.image.swf'
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											postNameConcat: function (name, idx){
							 | 
						||
| 
								 | 
							
												return	name + (idx != null ? '['+ idx +']' : '');
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											ext2mime: {
							 | 
						||
| 
								 | 
							
												  jpg:	'image/jpeg'
							 | 
						||
| 
								 | 
							
												, tif:	'image/tiff'
							 | 
						||
| 
								 | 
							
												, txt:	'text/plain'
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Fallback for flash
							 | 
						||
| 
								 | 
							
											accept: {
							 | 
						||
| 
								 | 
							
												  'image/*': 'art bm bmp dwg dxf cbr cbz fif fpx gif ico iefs jfif jpe jpeg jpg jps jut mcf nap nif pbm pcx pgm pict pm png pnm qif qtif ras rast rf rp svf tga tif tiff xbm xbm xpm xwd'
							 | 
						||
| 
								 | 
							
												, 'audio/*': 'm4a flac aac rm mpa wav wma ogg mp3 mp2 m3u mod amf dmf dsm far gdm imf it m15 med okt s3m stm sfx ult uni xm sid ac3 dts cue aif aiff wpl ape mac mpc mpp shn wv nsf spc gym adplug adx dsp adp ymf ast afc hps xs'
							 | 
						||
| 
								 | 
							
												, 'video/*': 'm4v 3gp nsv ts ty strm rm rmvb m3u ifo mov qt divx xvid bivx vob nrg img iso pva wmv asf asx ogm m2v avi bin dat dvr-ms mpg mpeg mp4 mkv avc vp3 svq3 nuv viv dv fli flv wpl'
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											uploadRetry : 0,
							 | 
						||
| 
								 | 
							
											networkDownRetryTimeout : 5000, // milliseconds, don't flood when network is down
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											chunkSize : 0,
							 | 
						||
| 
								 | 
							
											chunkUploadRetry : 0,
							 | 
						||
| 
								 | 
							
											chunkNetworkDownRetryTimeout : 2000, // milliseconds, don't flood when network is down
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											KB: _SIZE_CONST(1),
							 | 
						||
| 
								 | 
							
											MB: _SIZE_CONST(2),
							 | 
						||
| 
								 | 
							
											GB: _SIZE_CONST(3),
							 | 
						||
| 
								 | 
							
											TB: _SIZE_CONST(4),
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											EMPTY_PNG: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQIW2NkAAIAAAoAAggA9GkAAAAASUVORK5CYII=',
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											expando: 'fileapi' + (new Date).getTime(),
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											uid: function (obj){
							 | 
						||
| 
								 | 
							
												return	obj
							 | 
						||
| 
								 | 
							
													? (obj[api.expando] = obj[api.expando] || api.uid())
							 | 
						||
| 
								 | 
							
													: (++gid, api.expando + gid)
							 | 
						||
| 
								 | 
							
												;
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											log: function (){
							 | 
						||
| 
								 | 
							
												if( api.debug && window.console && console.log ){
							 | 
						||
| 
								 | 
							
													if( console.log.apply ){
							 | 
						||
| 
								 | 
							
														console.log.apply(console, arguments);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													else {
							 | 
						||
| 
								 | 
							
														console.log([].join.call(arguments, ' '));
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * Create new image
							 | 
						||
| 
								 | 
							
											 *
							 | 
						||
| 
								 | 
							
											 * @param {String} [src]
							 | 
						||
| 
								 | 
							
											 * @param {Function} [fn]   1. error -- boolean, 2. img -- Image element
							 | 
						||
| 
								 | 
							
											 * @returns {HTMLElement}
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											newImage: function (src, fn){
							 | 
						||
| 
								 | 
							
												var img = document.createElement('img');
							 | 
						||
| 
								 | 
							
												if( fn ){
							 | 
						||
| 
								 | 
							
													api.event.one(img, 'error load', function (evt){
							 | 
						||
| 
								 | 
							
														fn(evt.type == 'error', img);
							 | 
						||
| 
								 | 
							
														img = null;
							 | 
						||
| 
								 | 
							
													});
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												img.src = src;
							 | 
						||
| 
								 | 
							
												return	img;
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * Get XHR
							 | 
						||
| 
								 | 
							
											 * @returns {XMLHttpRequest}
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											getXHR: function (){
							 | 
						||
| 
								 | 
							
												var xhr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( XMLHttpRequest ){
							 | 
						||
| 
								 | 
							
													xhr = new XMLHttpRequest;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else if( window.ActiveXObject ){
							 | 
						||
| 
								 | 
							
													try {
							 | 
						||
| 
								 | 
							
														xhr = new ActiveXObject('MSXML2.XMLHttp.3.0');
							 | 
						||
| 
								 | 
							
													} catch (e) {
							 | 
						||
| 
								 | 
							
														xhr = new ActiveXObject('Microsoft.XMLHTTP');
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												return  xhr;
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											isArray: _isArray,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											support: {
							 | 
						||
| 
								 | 
							
												dnd:     cors && ('ondrop' in document.createElement('div')),
							 | 
						||
| 
								 | 
							
												cors:    cors,
							 | 
						||
| 
								 | 
							
												html5:   html5,
							 | 
						||
| 
								 | 
							
												chunked: chunked,
							 | 
						||
| 
								 | 
							
												dataURI: true,
							 | 
						||
| 
								 | 
							
												accept:   _supportInputAttr('accept'),
							 | 
						||
| 
								 | 
							
												multiple: _supportInputAttr('multiple')
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											event: {
							 | 
						||
| 
								 | 
							
												  on: _on
							 | 
						||
| 
								 | 
							
												, off: _off
							 | 
						||
| 
								 | 
							
												, one: _one
							 | 
						||
| 
								 | 
							
												, fix: _fixEvent
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											throttle: function(fn, delay) {
							 | 
						||
| 
								 | 
							
												var id, args;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												return function _throttle(){
							 | 
						||
| 
								 | 
							
													args = arguments;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													if( !id ){
							 | 
						||
| 
								 | 
							
														fn.apply(window, args);
							 | 
						||
| 
								 | 
							
														id = setTimeout(function (){
							 | 
						||
| 
								 | 
							
															id = 0;
							 | 
						||
| 
								 | 
							
															fn.apply(window, args);
							 | 
						||
| 
								 | 
							
														}, delay);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												};
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											F: function (){},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											parseJSON: function (str){
							 | 
						||
| 
								 | 
							
												var json;
							 | 
						||
| 
								 | 
							
												if( window.JSON && JSON.parse ){
							 | 
						||
| 
								 | 
							
													json = JSON.parse(str);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else {
							 | 
						||
| 
								 | 
							
													json = (new Function('return ('+str.replace(/([\r\n])/g, '\\$1')+');'))();
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												return json;
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											trim: function (str){
							 | 
						||
| 
								 | 
							
												str = String(str);
							 | 
						||
| 
								 | 
							
												return	str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, '');
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * Simple Defer
							 | 
						||
| 
								 | 
							
											 * @return	{Object}
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											defer: function (){
							 | 
						||
| 
								 | 
							
												var
							 | 
						||
| 
								 | 
							
													  list = []
							 | 
						||
| 
								 | 
							
													, result
							 | 
						||
| 
								 | 
							
													, error
							 | 
						||
| 
								 | 
							
													, defer = {
							 | 
						||
| 
								 | 
							
														resolve: function (err, res){
							 | 
						||
| 
								 | 
							
															defer.resolve = noop;
							 | 
						||
| 
								 | 
							
															error	= err || false;
							 | 
						||
| 
								 | 
							
															result	= res;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															while( res = list.shift() ){
							 | 
						||
| 
								 | 
							
																res(error, result);
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
														},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														then: function (fn){
							 | 
						||
| 
								 | 
							
															if( error !== undef ){
							 | 
						||
| 
								 | 
							
																fn(error, result);
							 | 
						||
| 
								 | 
							
															} else {
							 | 
						||
| 
								 | 
							
																list.push(fn);
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
												};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												return	defer;
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											queue: function (fn){
							 | 
						||
| 
								 | 
							
												var
							 | 
						||
| 
								 | 
							
													  _idx = 0
							 | 
						||
| 
								 | 
							
													, _length = 0
							 | 
						||
| 
								 | 
							
													, _fail = false
							 | 
						||
| 
								 | 
							
													, _end = false
							 | 
						||
| 
								 | 
							
													, queue = {
							 | 
						||
| 
								 | 
							
														inc: function (){
							 | 
						||
| 
								 | 
							
															_length++;
							 | 
						||
| 
								 | 
							
														},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														next: function (){
							 | 
						||
| 
								 | 
							
															_idx++;
							 | 
						||
| 
								 | 
							
															setTimeout(queue.check, 0);
							 | 
						||
| 
								 | 
							
														},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														check: function (){
							 | 
						||
| 
								 | 
							
															(_idx >= _length) && !_fail && queue.end();
							 | 
						||
| 
								 | 
							
														},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														isFail: function (){
							 | 
						||
| 
								 | 
							
															return _fail;
							 | 
						||
| 
								 | 
							
														},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														fail: function (){
							 | 
						||
| 
								 | 
							
															!_fail && fn(_fail = true);
							 | 
						||
| 
								 | 
							
														},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														end: function (){
							 | 
						||
| 
								 | 
							
															if( !_end ){
							 | 
						||
| 
								 | 
							
																_end = true;
							 | 
						||
| 
								 | 
							
																fn();
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												;
							 | 
						||
| 
								 | 
							
												return queue;
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * For each object
							 | 
						||
| 
								 | 
							
											 *
							 | 
						||
| 
								 | 
							
											 * @param	{Object|Array}	obj
							 | 
						||
| 
								 | 
							
											 * @param	{Function}		fn
							 | 
						||
| 
								 | 
							
											 * @param	{*}				[ctx]
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											each: _each,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * Async for
							 | 
						||
| 
								 | 
							
											 * @param {Array} array
							 | 
						||
| 
								 | 
							
											 * @param {Function} callback
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											afor: function (array, callback){
							 | 
						||
| 
								 | 
							
												var i = 0, n = array.length;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( _isArray(array) && n-- ){
							 | 
						||
| 
								 | 
							
													(function _next(){
							 | 
						||
| 
								 | 
							
														callback(n != i && _next, array[i], i++);
							 | 
						||
| 
								 | 
							
													})();
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else {
							 | 
						||
| 
								 | 
							
													callback(false);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * Merge the contents of two or more objects together into the first object
							 | 
						||
| 
								 | 
							
											 *
							 | 
						||
| 
								 | 
							
											 * @param	{Object}	dst
							 | 
						||
| 
								 | 
							
											 * @return	{Object}
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											extend: _extend,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * Is file?
							 | 
						||
| 
								 | 
							
											 * @param  {File}  file
							 | 
						||
| 
								 | 
							
											 * @return {Boolean}
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											isFile: function (file){
							 | 
						||
| 
								 | 
							
												return _toString.call(file) === '[object File]';
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * Is blob?
							 | 
						||
| 
								 | 
							
											 * @param   {Blob}  blob
							 | 
						||
| 
								 | 
							
											 * @returns {Boolean}
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											isBlob: function (blob) {
							 | 
						||
| 
								 | 
							
												return this.isFile(blob) || (_toString.call(blob) === '[object Blob]');
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * Is canvas element
							 | 
						||
| 
								 | 
							
											 *
							 | 
						||
| 
								 | 
							
											 * @param	{HTMLElement}	el
							 | 
						||
| 
								 | 
							
											 * @return	{Boolean}
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											isCanvas: function (el){
							 | 
						||
| 
								 | 
							
												return	el && _rcanvas.test(el.nodeName);
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											getFilesFilter: function (filter){
							 | 
						||
| 
								 | 
							
												filter = typeof filter == 'string' ? filter : (filter.getAttribute && filter.getAttribute('accept') || '');
							 | 
						||
| 
								 | 
							
												return	filter ? new RegExp('('+ filter.replace(/\./g, '\\.').replace(/,/g, '|') +')$', 'i') : /./;
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * Read as DataURL
							 | 
						||
| 
								 | 
							
											 *
							 | 
						||
| 
								 | 
							
											 * @param {File|Element} file
							 | 
						||
| 
								 | 
							
											 * @param {Function} fn
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											readAsDataURL: function (file, fn){
							 | 
						||
| 
								 | 
							
												if( api.isCanvas(file) ){
							 | 
						||
| 
								 | 
							
													_emit(file, fn, 'load', api.toDataURL(file));
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else {
							 | 
						||
| 
								 | 
							
													_readAs(file, fn, 'DataURL');
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * Read as Binary string
							 | 
						||
| 
								 | 
							
											 *
							 | 
						||
| 
								 | 
							
											 * @param {File} file
							 | 
						||
| 
								 | 
							
											 * @param {Function} fn
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											readAsBinaryString: function (file, fn){
							 | 
						||
| 
								 | 
							
												if( _hasSupportReadAs('BinaryString') ){
							 | 
						||
| 
								 | 
							
													_readAs(file, fn, 'BinaryString');
							 | 
						||
| 
								 | 
							
												} else {
							 | 
						||
| 
								 | 
							
													// Hello IE10!
							 | 
						||
| 
								 | 
							
													_readAs(file, function (evt){
							 | 
						||
| 
								 | 
							
														if( evt.type == 'load' ){
							 | 
						||
| 
								 | 
							
															try {
							 | 
						||
| 
								 | 
							
																// dataURL -> binaryString
							 | 
						||
| 
								 | 
							
																evt.result = api.toBinaryString(evt.result);
							 | 
						||
| 
								 | 
							
															} catch (e){
							 | 
						||
| 
								 | 
							
																evt.type = 'error';
							 | 
						||
| 
								 | 
							
																evt.message = e.toString();
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
														fn(evt);
							 | 
						||
| 
								 | 
							
													}, 'DataURL');
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * Read as ArrayBuffer
							 | 
						||
| 
								 | 
							
											 *
							 | 
						||
| 
								 | 
							
											 * @param {File} file
							 | 
						||
| 
								 | 
							
											 * @param {Function} fn
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											readAsArrayBuffer: function(file, fn){
							 | 
						||
| 
								 | 
							
												_readAs(file, fn, 'ArrayBuffer');
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * Read as text
							 | 
						||
| 
								 | 
							
											 *
							 | 
						||
| 
								 | 
							
											 * @param {File} file
							 | 
						||
| 
								 | 
							
											 * @param {String} encoding
							 | 
						||
| 
								 | 
							
											 * @param {Function} [fn]
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											readAsText: function(file, encoding, fn){
							 | 
						||
| 
								 | 
							
												if( !fn ){
							 | 
						||
| 
								 | 
							
													fn	= encoding;
							 | 
						||
| 
								 | 
							
													encoding = 'utf-8';
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												_readAs(file, fn, 'Text', encoding);
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * Convert image or canvas to DataURL
							 | 
						||
| 
								 | 
							
											 *
							 | 
						||
| 
								 | 
							
											 * @param   {Element}  el      Image or Canvas element
							 | 
						||
| 
								 | 
							
											 * @param   {String}   [type]  mime-type
							 | 
						||
| 
								 | 
							
											 * @return  {String}
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											toDataURL: function (el, type){
							 | 
						||
| 
								 | 
							
												if( typeof el == 'string' ){
							 | 
						||
| 
								 | 
							
													return  el;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else if( el.toDataURL ){
							 | 
						||
| 
								 | 
							
													return  el.toDataURL(type || 'image/png');
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * Canvert string, image or canvas to binary string
							 | 
						||
| 
								 | 
							
											 *
							 | 
						||
| 
								 | 
							
											 * @param   {String|Element} val
							 | 
						||
| 
								 | 
							
											 * @return  {String}
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											toBinaryString: function (val){
							 | 
						||
| 
								 | 
							
												return  window.atob(api.toDataURL(val).replace(_rdata, ''));
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * Read file or DataURL as ImageElement
							 | 
						||
| 
								 | 
							
											 *
							 | 
						||
| 
								 | 
							
											 * @param	{File|String}	file
							 | 
						||
| 
								 | 
							
											 * @param	{Function}		fn
							 | 
						||
| 
								 | 
							
											 * @param	{Boolean}		[progress]
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											readAsImage: function (file, fn, progress){
							 | 
						||
| 
								 | 
							
												if( api.isFile(file) ){
							 | 
						||
| 
								 | 
							
													if( apiURL ){
							 | 
						||
| 
								 | 
							
														/** @namespace apiURL.createObjectURL */
							 | 
						||
| 
								 | 
							
														var data = apiURL.createObjectURL(file);
							 | 
						||
| 
								 | 
							
														if( data === undef ){
							 | 
						||
| 
								 | 
							
															_emit(file, fn, 'error');
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
														else {
							 | 
						||
| 
								 | 
							
															api.readAsImage(data, fn, progress);
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													else {
							 | 
						||
| 
								 | 
							
														api.readAsDataURL(file, function (evt){
							 | 
						||
| 
								 | 
							
															if( evt.type == 'load' ){
							 | 
						||
| 
								 | 
							
																api.readAsImage(evt.result, fn, progress);
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
															else if( progress || evt.type == 'error' ){
							 | 
						||
| 
								 | 
							
																_emit(file, fn, evt, null, { loaded: evt.loaded, total: evt.total });
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
														});
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else if( api.isCanvas(file) ){
							 | 
						||
| 
								 | 
							
													_emit(file, fn, 'load', file);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else if( _rimg.test(file.nodeName) ){
							 | 
						||
| 
								 | 
							
													if( file.complete ){
							 | 
						||
| 
								 | 
							
														_emit(file, fn, 'load', file);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													else {
							 | 
						||
| 
								 | 
							
														var events = 'error abort load';
							 | 
						||
| 
								 | 
							
														_one(file, events, function _fn(evt){
							 | 
						||
| 
								 | 
							
															if( evt.type == 'load' && apiURL ){
							 | 
						||
| 
								 | 
							
																/** @namespace apiURL.revokeObjectURL */
							 | 
						||
| 
								 | 
							
																apiURL.revokeObjectURL(file.src);
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															_off(file, events, _fn);
							 | 
						||
| 
								 | 
							
															_emit(file, fn, evt, file);
							 | 
						||
| 
								 | 
							
														});
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else if( file.iframe ){
							 | 
						||
| 
								 | 
							
													_emit(file, fn, { type: 'error' });
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else {
							 | 
						||
| 
								 | 
							
													// Created image
							 | 
						||
| 
								 | 
							
													var img = api.newImage(file.dataURL || file);
							 | 
						||
| 
								 | 
							
													api.readAsImage(img, fn, progress);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * Make file by name
							 | 
						||
| 
								 | 
							
											 *
							 | 
						||
| 
								 | 
							
											 * @param	{String}	name
							 | 
						||
| 
								 | 
							
											 * @return	{Array}
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											checkFileObj: function (name){
							 | 
						||
| 
								 | 
							
												var file = {}, accept = api.accept;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( typeof name == 'object' ){
							 | 
						||
| 
								 | 
							
													file = name;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else {
							 | 
						||
| 
								 | 
							
													file.name = (name + '').split(/\\|\//g).pop();
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( file.type == null ){
							 | 
						||
| 
								 | 
							
													file.type = file.name.split('.').pop();
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												_each(accept, function (ext, type){
							 | 
						||
| 
								 | 
							
													ext = new RegExp(ext.replace(/\s/g, '|'), 'i');
							 | 
						||
| 
								 | 
							
													if( ext.test(file.type) || api.ext2mime[file.type] ){
							 | 
						||
| 
								 | 
							
														file.type = api.ext2mime[file.type] || (type.split('/')[0] +'/'+ file.type);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												return	file;
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * Get drop files
							 | 
						||
| 
								 | 
							
											 *
							 | 
						||
| 
								 | 
							
											 * @param	{Event}	evt
							 | 
						||
| 
								 | 
							
											 * @param	{Function} callback
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											getDropFiles: function (evt, callback){
							 | 
						||
| 
								 | 
							
												var
							 | 
						||
| 
								 | 
							
													  files = []
							 | 
						||
| 
								 | 
							
													, dataTransfer = _getDataTransfer(evt)
							 | 
						||
| 
								 | 
							
													, entrySupport = _isArray(dataTransfer.items) && dataTransfer.items[0] && _getAsEntry(dataTransfer.items[0])
							 | 
						||
| 
								 | 
							
													, queue = api.queue(function (){ callback(files); })
							 | 
						||
| 
								 | 
							
												;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												_each((entrySupport ? dataTransfer.items : dataTransfer.files) || [], function (item){
							 | 
						||
| 
								 | 
							
													queue.inc();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													try {
							 | 
						||
| 
								 | 
							
														if( entrySupport ){
							 | 
						||
| 
								 | 
							
															_readEntryAsFiles(item, function (err, entryFiles){
							 | 
						||
| 
								 | 
							
																if( err ){
							 | 
						||
| 
								 | 
							
																	api.log('[err] getDropFiles:', err);
							 | 
						||
| 
								 | 
							
																} else {
							 | 
						||
| 
								 | 
							
																	files.push.apply(files, entryFiles);
							 | 
						||
| 
								 | 
							
																}
							 | 
						||
| 
								 | 
							
																queue.next();
							 | 
						||
| 
								 | 
							
															});
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
														else {
							 | 
						||
| 
								 | 
							
															_isRegularFile(item, function (yes){
							 | 
						||
| 
								 | 
							
																yes && files.push(item);
							 | 
						||
| 
								 | 
							
																queue.next();
							 | 
						||
| 
								 | 
							
															});
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													catch( err ){
							 | 
						||
| 
								 | 
							
														queue.next();
							 | 
						||
| 
								 | 
							
														api.log('[err] getDropFiles: ', err);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												queue.check();
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * Get file list
							 | 
						||
| 
								 | 
							
											 *
							 | 
						||
| 
								 | 
							
											 * @param	{HTMLInputElement|Event}	input
							 | 
						||
| 
								 | 
							
											 * @param	{String|Function}	[filter]
							 | 
						||
| 
								 | 
							
											 * @param	{Function}			[callback]
							 | 
						||
| 
								 | 
							
											 * @return	{Array|Null}
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											getFiles: function (input, filter, callback){
							 | 
						||
| 
								 | 
							
												var files = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( callback ){
							 | 
						||
| 
								 | 
							
													api.filterFiles(api.getFiles(input), filter, callback);
							 | 
						||
| 
								 | 
							
													return null;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( input.jquery ){
							 | 
						||
| 
								 | 
							
													// jQuery object
							 | 
						||
| 
								 | 
							
													input.each(function (){
							 | 
						||
| 
								 | 
							
														files = files.concat(api.getFiles(this));
							 | 
						||
| 
								 | 
							
													});
							 | 
						||
| 
								 | 
							
													input	= files;
							 | 
						||
| 
								 | 
							
													files	= [];
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( typeof filter == 'string' ){
							 | 
						||
| 
								 | 
							
													filter	= api.getFilesFilter(filter);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( input.originalEvent ){
							 | 
						||
| 
								 | 
							
													// jQuery event
							 | 
						||
| 
								 | 
							
													input = _fixEvent(input.originalEvent);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else if( input.srcElement ){
							 | 
						||
| 
								 | 
							
													// IE Event
							 | 
						||
| 
								 | 
							
													input = _fixEvent(input);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( input.dataTransfer ){
							 | 
						||
| 
								 | 
							
													// Drag'n'Drop
							 | 
						||
| 
								 | 
							
													input = input.dataTransfer;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else if( input.target ){
							 | 
						||
| 
								 | 
							
													// Event
							 | 
						||
| 
								 | 
							
													input = input.target;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( input.files ){
							 | 
						||
| 
								 | 
							
													// Input[type="file"]
							 | 
						||
| 
								 | 
							
													files = input.files;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													if( !html5 ){
							 | 
						||
| 
								 | 
							
														// Partial support for file api
							 | 
						||
| 
								 | 
							
														files[0].blob	= input;
							 | 
						||
| 
								 | 
							
														files[0].iframe	= true;
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else if( !html5 && isInputFile(input) ){
							 | 
						||
| 
								 | 
							
													if( api.trim(input.value) ){
							 | 
						||
| 
								 | 
							
														files = [api.checkFileObj(input.value)];
							 | 
						||
| 
								 | 
							
														files[0].blob   = input;
							 | 
						||
| 
								 | 
							
														files[0].iframe = true;
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else if( _isArray(input) ){
							 | 
						||
| 
								 | 
							
													files	= input;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												return	api.filter(files, function (file){ return !filter || filter.test(file.name); });
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * Get total file size
							 | 
						||
| 
								 | 
							
											 * @param	{Array}	files
							 | 
						||
| 
								 | 
							
											 * @return	{Number}
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											getTotalSize: function (files){
							 | 
						||
| 
								 | 
							
												var size = 0, i = files && files.length;
							 | 
						||
| 
								 | 
							
												while( i-- ){
							 | 
						||
| 
								 | 
							
													size += files[i].size;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												return	size;
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * Get image information
							 | 
						||
| 
								 | 
							
											 *
							 | 
						||
| 
								 | 
							
											 * @param	{File}		file
							 | 
						||
| 
								 | 
							
											 * @param	{Function}	fn
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											getInfo: function (file, fn){
							 | 
						||
| 
								 | 
							
												var info = {}, readers = _infoReader.concat();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( api.isFile(file) ){
							 | 
						||
| 
								 | 
							
													(function _next(){
							 | 
						||
| 
								 | 
							
														var reader = readers.shift();
							 | 
						||
| 
								 | 
							
														if( reader ){
							 | 
						||
| 
								 | 
							
															if( reader.test(file.type) ){
							 | 
						||
| 
								 | 
							
																reader(file, function (err, res){
							 | 
						||
| 
								 | 
							
																	if( err ){
							 | 
						||
| 
								 | 
							
																		fn(err);
							 | 
						||
| 
								 | 
							
																	}
							 | 
						||
| 
								 | 
							
																	else {
							 | 
						||
| 
								 | 
							
																		_extend(info, res);
							 | 
						||
| 
								 | 
							
																		_next();
							 | 
						||
| 
								 | 
							
																	}
							 | 
						||
| 
								 | 
							
																});
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
															else {
							 | 
						||
| 
								 | 
							
																_next();
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
														else {
							 | 
						||
| 
								 | 
							
															fn(false, info);
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													})();
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else {
							 | 
						||
| 
								 | 
							
													fn('not_support_info', info);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * Add information reader
							 | 
						||
| 
								 | 
							
											 *
							 | 
						||
| 
								 | 
							
											 * @param {RegExp} mime
							 | 
						||
| 
								 | 
							
											 * @param {Function} fn
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											addInfoReader: function (mime, fn){
							 | 
						||
| 
								 | 
							
												fn.test = function (type){ return mime.test(type); };
							 | 
						||
| 
								 | 
							
												_infoReader.push(fn);
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * Filter of array
							 | 
						||
| 
								 | 
							
											 *
							 | 
						||
| 
								 | 
							
											 * @param	{Array}		input
							 | 
						||
| 
								 | 
							
											 * @param	{Function}	fn
							 | 
						||
| 
								 | 
							
											 * @return	{Array}
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											filter: function (input, fn){
							 | 
						||
| 
								 | 
							
												var result = [], i = 0, n = input.length, val;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												for( ; i < n; i++ ){
							 | 
						||
| 
								 | 
							
													if( i in input ){
							 | 
						||
| 
								 | 
							
														val = input[i];
							 | 
						||
| 
								 | 
							
														if( fn.call(val, val, i, input) ){
							 | 
						||
| 
								 | 
							
															result.push(val);
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												return	result;
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * Filter files
							 | 
						||
| 
								 | 
							
											 *
							 | 
						||
| 
								 | 
							
											 * @param	{Array}		files
							 | 
						||
| 
								 | 
							
											 * @param	{Function}	eachFn
							 | 
						||
| 
								 | 
							
											 * @param	{Function}	resultFn
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											filterFiles: function (files, eachFn, resultFn){
							 | 
						||
| 
								 | 
							
												if( files.length ){
							 | 
						||
| 
								 | 
							
													// HTML5 or Flash
							 | 
						||
| 
								 | 
							
													var queue = files.concat(), file, result = [], deleted = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													(function _next(){
							 | 
						||
| 
								 | 
							
														if( queue.length ){
							 | 
						||
| 
								 | 
							
															file = queue.shift();
							 | 
						||
| 
								 | 
							
															api.getInfo(file, function (err, info){
							 | 
						||
| 
								 | 
							
																(eachFn(file, err ? false : info) ? result : deleted).push(file);
							 | 
						||
| 
								 | 
							
																_next();
							 | 
						||
| 
								 | 
							
															});
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
														else {
							 | 
						||
| 
								 | 
							
															resultFn(result, deleted);
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													})();
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else {
							 | 
						||
| 
								 | 
							
													resultFn([], files);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											upload: function (options){
							 | 
						||
| 
								 | 
							
												options = _extend({
							 | 
						||
| 
								 | 
							
													  jsonp: 'callback'
							 | 
						||
| 
								 | 
							
													, prepare: api.F
							 | 
						||
| 
								 | 
							
													, beforeupload: api.F
							 | 
						||
| 
								 | 
							
													, upload: api.F
							 | 
						||
| 
								 | 
							
													, fileupload: api.F
							 | 
						||
| 
								 | 
							
													, fileprogress: api.F
							 | 
						||
| 
								 | 
							
													, filecomplete: api.F
							 | 
						||
| 
								 | 
							
													, progress: api.F
							 | 
						||
| 
								 | 
							
													, complete: api.F
							 | 
						||
| 
								 | 
							
													, pause: api.F
							 | 
						||
| 
								 | 
							
													, imageOriginal: true
							 | 
						||
| 
								 | 
							
													, chunkSize: api.chunkSize
							 | 
						||
| 
								 | 
							
													, chunkUploadRetry: api.chunkUploadRetry
							 | 
						||
| 
								 | 
							
													, uploadRetry: api.uploadRetry
							 | 
						||
| 
								 | 
							
												}, options);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( options.imageAutoOrientation && !options.imageTransform ){
							 | 
						||
| 
								 | 
							
													options.imageTransform = { rotate: 'auto' };
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												var
							 | 
						||
| 
								 | 
							
													  proxyXHR = new api.XHR(options)
							 | 
						||
| 
								 | 
							
													, dataArray = this._getFilesDataArray(options.files)
							 | 
						||
| 
								 | 
							
													, _this = this
							 | 
						||
| 
								 | 
							
													, _total = 0
							 | 
						||
| 
								 | 
							
													, _loaded = 0
							 | 
						||
| 
								 | 
							
													, _nextFile
							 | 
						||
| 
								 | 
							
													, _complete = false
							 | 
						||
| 
								 | 
							
												;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// calc total size
							 | 
						||
| 
								 | 
							
												_each(dataArray, function (data){
							 | 
						||
| 
								 | 
							
													_total += data.size;
							 | 
						||
| 
								 | 
							
												});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// Array of files
							 | 
						||
| 
								 | 
							
												proxyXHR.files = [];
							 | 
						||
| 
								 | 
							
												_each(dataArray, function (data){
							 | 
						||
| 
								 | 
							
													proxyXHR.files.push(data.file);
							 | 
						||
| 
								 | 
							
												});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// Set upload status props
							 | 
						||
| 
								 | 
							
												proxyXHR.total	= _total;
							 | 
						||
| 
								 | 
							
												proxyXHR.loaded	= 0;
							 | 
						||
| 
								 | 
							
												proxyXHR.filesLeft = dataArray.length;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// emit "beforeupload"  event
							 | 
						||
| 
								 | 
							
												options.beforeupload(proxyXHR, options);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// Upload by file
							 | 
						||
| 
								 | 
							
												_nextFile = function (){
							 | 
						||
| 
								 | 
							
													var
							 | 
						||
| 
								 | 
							
														  data = dataArray.shift()
							 | 
						||
| 
								 | 
							
														, _file = data && data.file
							 | 
						||
| 
								 | 
							
														, _fileLoaded = false
							 | 
						||
| 
								 | 
							
														, _fileOptions = _simpleClone(options)
							 | 
						||
| 
								 | 
							
													;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													proxyXHR.filesLeft = dataArray.length;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													if( _file && _file.name === api.expando ){
							 | 
						||
| 
								 | 
							
														_file = null;
							 | 
						||
| 
								 | 
							
														api.log('[warn] FileAPI.upload() — called without files');
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													if( ( proxyXHR.statusText != 'abort' || proxyXHR.current ) && data ){
							 | 
						||
| 
								 | 
							
														// Mark active job
							 | 
						||
| 
								 | 
							
														_complete = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														// Set current upload file
							 | 
						||
| 
								 | 
							
														proxyXHR.currentFile = _file;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														// Prepare file options
							 | 
						||
| 
								 | 
							
														if (_file && options.prepare(_file, _fileOptions) === false) {
							 | 
						||
| 
								 | 
							
															_nextFile.call(_this);
							 | 
						||
| 
								 | 
							
															return;
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
														_fileOptions.file = _file;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														_this._getFormData(_fileOptions, data, function (form){
							 | 
						||
| 
								 | 
							
															if( !_loaded ){
							 | 
						||
| 
								 | 
							
																// emit "upload" event
							 | 
						||
| 
								 | 
							
																options.upload(proxyXHR, options);
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															var xhr = new api.XHR(_extend({}, _fileOptions, {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																upload: _file ? function (){
							 | 
						||
| 
								 | 
							
																	// emit "fileupload" event
							 | 
						||
| 
								 | 
							
																	options.fileupload(_file, xhr, _fileOptions);
							 | 
						||
| 
								 | 
							
																} : noop,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																progress: _file ? function (evt){
							 | 
						||
| 
								 | 
							
																	if( !_fileLoaded ){
							 | 
						||
| 
								 | 
							
																		// For ignore the double calls.
							 | 
						||
| 
								 | 
							
																		_fileLoaded = (evt.loaded === evt.total);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																		// emit "fileprogress" event
							 | 
						||
| 
								 | 
							
																		options.fileprogress({
							 | 
						||
| 
								 | 
							
																			  type:   'progress'
							 | 
						||
| 
								 | 
							
																			, total:  data.total = evt.total
							 | 
						||
| 
								 | 
							
																			, loaded: data.loaded = evt.loaded
							 | 
						||
| 
								 | 
							
																		}, _file, xhr, _fileOptions);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																		// emit "progress" event
							 | 
						||
| 
								 | 
							
																		options.progress({
							 | 
						||
| 
								 | 
							
																			  type:   'progress'
							 | 
						||
| 
								 | 
							
																			, total:  _total
							 | 
						||
| 
								 | 
							
																			, loaded: proxyXHR.loaded = (_loaded + data.size * (evt.loaded/evt.total))|0
							 | 
						||
| 
								 | 
							
																		}, _file, xhr, _fileOptions);
							 | 
						||
| 
								 | 
							
																	}
							 | 
						||
| 
								 | 
							
																} : noop,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																complete: function (err){
							 | 
						||
| 
								 | 
							
																	_each(_xhrPropsExport, function (name){
							 | 
						||
| 
								 | 
							
																		proxyXHR[name] = xhr[name];
							 | 
						||
| 
								 | 
							
																	});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																	if( _file ){
							 | 
						||
| 
								 | 
							
																		data.total = (data.total || data.size);
							 | 
						||
| 
								 | 
							
																		data.loaded	= data.total;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																		if( !err ) {
							 | 
						||
| 
								 | 
							
																			// emulate 100% "progress"
							 | 
						||
| 
								 | 
							
																			this.progress(data);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																			// fixed throttle event
							 | 
						||
| 
								 | 
							
																			_fileLoaded = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																			// bytes loaded
							 | 
						||
| 
								 | 
							
																			_loaded += data.size; // data.size != data.total, it's desirable fix this
							 | 
						||
| 
								 | 
							
																			proxyXHR.loaded = _loaded;
							 | 
						||
| 
								 | 
							
																		}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																		// emit "filecomplete" event
							 | 
						||
| 
								 | 
							
																		options.filecomplete(err, xhr, _file, _fileOptions);
							 | 
						||
| 
								 | 
							
																	}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																	// upload next file
							 | 
						||
| 
								 | 
							
																	setTimeout(function () {_nextFile.call(_this);}, 0);
							 | 
						||
| 
								 | 
							
																}
							 | 
						||
| 
								 | 
							
															})); // xhr
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															// ...
							 | 
						||
| 
								 | 
							
															proxyXHR.abort = function (current){
							 | 
						||
| 
								 | 
							
																if (!current) { dataArray.length = 0; }
							 | 
						||
| 
								 | 
							
																this.current = current;
							 | 
						||
| 
								 | 
							
																xhr.abort();
							 | 
						||
| 
								 | 
							
															};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															// Start upload
							 | 
						||
| 
								 | 
							
															xhr.send(form);
							 | 
						||
| 
								 | 
							
														});
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													else {
							 | 
						||
| 
								 | 
							
														var successful = proxyXHR.status == 200 || proxyXHR.status == 201 || proxyXHR.status == 204;
							 | 
						||
| 
								 | 
							
														options.complete(successful ? false : (proxyXHR.statusText || 'error'), proxyXHR, options);
							 | 
						||
| 
								 | 
							
														// Mark done state
							 | 
						||
| 
								 | 
							
														_complete = true;
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// Next tick
							 | 
						||
| 
								 | 
							
												setTimeout(_nextFile, 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// Append more files to the existing request
							 | 
						||
| 
								 | 
							
												// first - add them to the queue head/tail
							 | 
						||
| 
								 | 
							
												proxyXHR.append = function (files, first) {
							 | 
						||
| 
								 | 
							
													files = api._getFilesDataArray([].concat(files));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													_each(files, function (data) {
							 | 
						||
| 
								 | 
							
														_total += data.size;
							 | 
						||
| 
								 | 
							
														proxyXHR.files.push(data.file);
							 | 
						||
| 
								 | 
							
														if (first) {
							 | 
						||
| 
								 | 
							
															dataArray.unshift(data);
							 | 
						||
| 
								 | 
							
														} else {
							 | 
						||
| 
								 | 
							
															dataArray.push(data);
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													proxyXHR.statusText = "";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													if( _complete ){
							 | 
						||
| 
								 | 
							
														_nextFile.call(_this);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// Removes file from queue by file reference and returns it
							 | 
						||
| 
								 | 
							
												proxyXHR.remove = function (file) {
							 | 
						||
| 
								 | 
							
												    var i = dataArray.length, _file;
							 | 
						||
| 
								 | 
							
												    while( i-- ){
							 | 
						||
| 
								 | 
							
														if( dataArray[i].file == file ){
							 | 
						||
| 
								 | 
							
															_file = dataArray.splice(i, 1);
							 | 
						||
| 
								 | 
							
															_total -= _file.size;
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													return	_file;
							 | 
						||
| 
								 | 
							
												};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												return proxyXHR;
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											_getFilesDataArray: function (data){
							 | 
						||
| 
								 | 
							
												var files = [], oFiles = {};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( isInputFile(data) ){
							 | 
						||
| 
								 | 
							
													var tmp = api.getFiles(data);
							 | 
						||
| 
								 | 
							
													oFiles[data.name || 'file'] = data.getAttribute('multiple') !== null ? tmp : tmp[0];
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else if( _isArray(data) && isInputFile(data[0]) ){
							 | 
						||
| 
								 | 
							
													_each(data, function (input){
							 | 
						||
| 
								 | 
							
														oFiles[input.name || 'file'] = api.getFiles(input);
							 | 
						||
| 
								 | 
							
													});
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else {
							 | 
						||
| 
								 | 
							
													oFiles = data;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												_each(oFiles, function add(file, name){
							 | 
						||
| 
								 | 
							
													if( _isArray(file) ){
							 | 
						||
| 
								 | 
							
														_each(file, function (file){
							 | 
						||
| 
								 | 
							
															add(file, name);
							 | 
						||
| 
								 | 
							
														});
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													else if( file && (file.name || file.image) ){
							 | 
						||
| 
								 | 
							
														files.push({
							 | 
						||
| 
								 | 
							
															  name: name
							 | 
						||
| 
								 | 
							
															, file: file
							 | 
						||
| 
								 | 
							
															, size: file.size
							 | 
						||
| 
								 | 
							
															, total: file.size
							 | 
						||
| 
								 | 
							
															, loaded: 0
							 | 
						||
| 
								 | 
							
														});
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( !files.length ){
							 | 
						||
| 
								 | 
							
													// Create fake `file` object
							 | 
						||
| 
								 | 
							
													files.push({ file: { name: api.expando } });
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												return	files;
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											_getFormData: function (options, data, fn){
							 | 
						||
| 
								 | 
							
												var
							 | 
						||
| 
								 | 
							
													  file = data.file
							 | 
						||
| 
								 | 
							
													, name = data.name
							 | 
						||
| 
								 | 
							
													, filename = file.name
							 | 
						||
| 
								 | 
							
													, filetype = file.type
							 | 
						||
| 
								 | 
							
													, trans = api.support.transform && options.imageTransform
							 | 
						||
| 
								 | 
							
													, Form = new api.Form
							 | 
						||
| 
								 | 
							
													, queue = api.queue(function (){ fn(Form); })
							 | 
						||
| 
								 | 
							
													, isOrignTrans = trans && _isOriginTransform(trans)
							 | 
						||
| 
								 | 
							
													, postNameConcat = api.postNameConcat
							 | 
						||
| 
								 | 
							
												;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// Append data
							 | 
						||
| 
								 | 
							
												_each(options.data, function add(val, name){
							 | 
						||
| 
								 | 
							
													if( typeof val == 'object' ){
							 | 
						||
| 
								 | 
							
														_each(val, function (v, i){
							 | 
						||
| 
								 | 
							
															add(v, postNameConcat(name, i));
							 | 
						||
| 
								 | 
							
														});
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													else {
							 | 
						||
| 
								 | 
							
														Form.append(name, val);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												(function _addFile(file/**Object*/){
							 | 
						||
| 
								 | 
							
													if( file.image ){ // This is a FileAPI.Image
							 | 
						||
| 
								 | 
							
														queue.inc();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														file.toData(function (err, image){
							 | 
						||
| 
								 | 
							
															// @todo: error
							 | 
						||
| 
								 | 
							
															filename = filename || (new Date).getTime()+'.png';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															_addFile(image);
							 | 
						||
| 
								 | 
							
															queue.next();
							 | 
						||
| 
								 | 
							
														});
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													else if( api.Image && trans && (/^image/.test(file.type) || _rimgcanvas.test(file.nodeName)) ){
							 | 
						||
| 
								 | 
							
														queue.inc();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														if( isOrignTrans ){
							 | 
						||
| 
								 | 
							
															// Convert to array for transform function
							 | 
						||
| 
								 | 
							
															trans = [trans];
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														api.Image.transform(file, trans, options.imageAutoOrientation, function (err, images){
							 | 
						||
| 
								 | 
							
															if( isOrignTrans && !err ){
							 | 
						||
| 
								 | 
							
																if( !dataURLtoBlob && !api.flashEngine ){
							 | 
						||
| 
								 | 
							
																	// Canvas.toBlob or Flash not supported, use multipart
							 | 
						||
| 
								 | 
							
																	Form.multipart = true;
							 | 
						||
| 
								 | 
							
																}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																Form.append(name, images[0], filename,  trans[0].type || filetype);
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
															else {
							 | 
						||
| 
								 | 
							
																var addOrigin = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																if( !err ){
							 | 
						||
| 
								 | 
							
																	_each(images, function (image, idx){
							 | 
						||
| 
								 | 
							
																		if( !dataURLtoBlob && !api.flashEngine ){
							 | 
						||
| 
								 | 
							
																			Form.multipart = true;
							 | 
						||
| 
								 | 
							
																		}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																		if( !trans[idx].postName ){
							 | 
						||
| 
								 | 
							
																			addOrigin = 1;
							 | 
						||
| 
								 | 
							
																		}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																		Form.append(trans[idx].postName || postNameConcat(name, idx), image, filename, trans[idx].type || filetype);
							 | 
						||
| 
								 | 
							
																	});
							 | 
						||
| 
								 | 
							
																}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																if( err || options.imageOriginal ){
							 | 
						||
| 
								 | 
							
																	Form.append(postNameConcat(name, (addOrigin ? 'original' : null)), file, filename, filetype);
							 | 
						||
| 
								 | 
							
																}
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															queue.next();
							 | 
						||
| 
								 | 
							
														});
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													else if( filename !== api.expando ){
							 | 
						||
| 
								 | 
							
														Form.append(name, file, filename);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												})(file);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												queue.check();
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											reset: function (inp, notRemove){
							 | 
						||
| 
								 | 
							
												var parent, clone;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( jQuery ){
							 | 
						||
| 
								 | 
							
													clone = jQuery(inp).clone(true).insertBefore(inp).val('')[0];
							 | 
						||
| 
								 | 
							
													if( !notRemove ){
							 | 
						||
| 
								 | 
							
														jQuery(inp).remove();
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												} else {
							 | 
						||
| 
								 | 
							
													parent  = inp.parentNode;
							 | 
						||
| 
								 | 
							
													clone   = parent.insertBefore(inp.cloneNode(true), inp);
							 | 
						||
| 
								 | 
							
													clone.value = '';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													if( !notRemove ){
							 | 
						||
| 
								 | 
							
														parent.removeChild(inp);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													_each(_elEvents[api.uid(inp)], function (fns, type){
							 | 
						||
| 
								 | 
							
														_each(fns, function (fn){
							 | 
						||
| 
								 | 
							
															_off(inp, type, fn);
							 | 
						||
| 
								 | 
							
															_on(clone, type, fn);
							 | 
						||
| 
								 | 
							
														});
							 | 
						||
| 
								 | 
							
													});
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												return  clone;
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/**
							 | 
						||
| 
								 | 
							
											 * Load remote file
							 | 
						||
| 
								 | 
							
											 *
							 | 
						||
| 
								 | 
							
											 * @param   {String}    url
							 | 
						||
| 
								 | 
							
											 * @param   {Function}  fn
							 | 
						||
| 
								 | 
							
											 * @return  {XMLHttpRequest}
							 | 
						||
| 
								 | 
							
											 */
							 | 
						||
| 
								 | 
							
											load: function (url, fn){
							 | 
						||
| 
								 | 
							
												var xhr = api.getXHR();
							 | 
						||
| 
								 | 
							
												if( xhr ){
							 | 
						||
| 
								 | 
							
													xhr.open('GET', url, true);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													if( xhr.overrideMimeType ){
							 | 
						||
| 
								 | 
							
												        xhr.overrideMimeType('text/plain; charset=x-user-defined');
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													_on(xhr, 'progress', function (/**Event*/evt){
							 | 
						||
| 
								 | 
							
														/** @namespace evt.lengthComputable */
							 | 
						||
| 
								 | 
							
														if( evt.lengthComputable ){
							 | 
						||
| 
								 | 
							
															fn({ type: evt.type, loaded: evt.loaded, total: evt.total }, xhr);
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													xhr.onreadystatechange = function(){
							 | 
						||
| 
								 | 
							
														if( xhr.readyState == 4 ){
							 | 
						||
| 
								 | 
							
															xhr.onreadystatechange = null;
							 | 
						||
| 
								 | 
							
															if( xhr.status == 200 ){
							 | 
						||
| 
								 | 
							
																url = url.split('/');
							 | 
						||
| 
								 | 
							
																/** @namespace xhr.responseBody */
							 | 
						||
| 
								 | 
							
																var file = {
							 | 
						||
| 
								 | 
							
																      name: url[url.length-1]
							 | 
						||
| 
								 | 
							
																	, size: xhr.getResponseHeader('Content-Length')
							 | 
						||
| 
								 | 
							
																	, type: xhr.getResponseHeader('Content-Type')
							 | 
						||
| 
								 | 
							
																};
							 | 
						||
| 
								 | 
							
																file.dataURL = 'data:'+file.type+';base64,' + api.encode64(xhr.responseBody || xhr.responseText);
							 | 
						||
| 
								 | 
							
																fn({ type: 'load', result: file }, xhr);
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
															else {
							 | 
						||
| 
								 | 
							
																fn({ type: 'error' }, xhr);
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
													    }
							 | 
						||
| 
								 | 
							
													};
							 | 
						||
| 
								 | 
							
												    xhr.send(null);
							 | 
						||
| 
								 | 
							
												} else {
							 | 
						||
| 
								 | 
							
													fn({ type: 'error' });
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												return  xhr;
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											encode64: function (str){
							 | 
						||
| 
								 | 
							
												var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', outStr = '', i = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( typeof str !== 'string' ){
							 | 
						||
| 
								 | 
							
													str	= String(str);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												while( i < str.length ){
							 | 
						||
| 
								 | 
							
													//all three "& 0xff" added below are there to fix a known bug
							 | 
						||
| 
								 | 
							
													//with bytes returned by xhr.responseText
							 | 
						||
| 
								 | 
							
													var
							 | 
						||
| 
								 | 
							
														  byte1 = str.charCodeAt(i++) & 0xff
							 | 
						||
| 
								 | 
							
														, byte2 = str.charCodeAt(i++) & 0xff
							 | 
						||
| 
								 | 
							
														, byte3 = str.charCodeAt(i++) & 0xff
							 | 
						||
| 
								 | 
							
														, enc1 = byte1 >> 2
							 | 
						||
| 
								 | 
							
														, enc2 = ((byte1 & 3) << 4) | (byte2 >> 4)
							 | 
						||
| 
								 | 
							
														, enc3, enc4
							 | 
						||
| 
								 | 
							
													;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													if( isNaN(byte2) ){
							 | 
						||
| 
								 | 
							
														enc3 = enc4 = 64;
							 | 
						||
| 
								 | 
							
													} else {
							 | 
						||
| 
								 | 
							
														enc3 = ((byte2 & 15) << 2) | (byte3 >> 6);
							 | 
						||
| 
								 | 
							
														enc4 = isNaN(byte3) ? 64 : byte3 & 63;
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													outStr += b64.charAt(enc1) + b64.charAt(enc2) + b64.charAt(enc3) + b64.charAt(enc4);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												return  outStr;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										} // api
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function _emit(target, fn, name, res, ext){
							 | 
						||
| 
								 | 
							
										var evt = {
							 | 
						||
| 
								 | 
							
											  type:		name.type || name
							 | 
						||
| 
								 | 
							
											, target:	target
							 | 
						||
| 
								 | 
							
											, result:	res
							 | 
						||
| 
								 | 
							
										};
							 | 
						||
| 
								 | 
							
										_extend(evt, ext);
							 | 
						||
| 
								 | 
							
										fn(evt);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function _hasSupportReadAs(as){
							 | 
						||
| 
								 | 
							
										return	FileReader && !!FileReader.prototype['readAs'+as];
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function _readAs(file, fn, as, encoding){
							 | 
						||
| 
								 | 
							
										if( api.isBlob(file) && _hasSupportReadAs(as) ){
							 | 
						||
| 
								 | 
							
											var Reader = new FileReader;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Add event listener
							 | 
						||
| 
								 | 
							
											_on(Reader, _readerEvents, function _fn(evt){
							 | 
						||
| 
								 | 
							
												var type = evt.type;
							 | 
						||
| 
								 | 
							
												if( type == 'progress' ){
							 | 
						||
| 
								 | 
							
													_emit(file, fn, evt, evt.target.result, { loaded: evt.loaded, total: evt.total });
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else if( type == 'loadend' ){
							 | 
						||
| 
								 | 
							
													_off(Reader, _readerEvents, _fn);
							 | 
						||
| 
								 | 
							
													Reader = null;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else {
							 | 
						||
| 
								 | 
							
													_emit(file, fn, evt, evt.target.result);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											try {
							 | 
						||
| 
								 | 
							
												// ReadAs ...
							 | 
						||
| 
								 | 
							
												if( encoding ){
							 | 
						||
| 
								 | 
							
													Reader['readAs'+as](file, encoding);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else {
							 | 
						||
| 
								 | 
							
													Reader['readAs'+as](file);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											catch (err){
							 | 
						||
| 
								 | 
							
												_emit(file, fn, 'error', undef, { error: err.toString() });
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else {
							 | 
						||
| 
								 | 
							
											_emit(file, fn, 'error', undef, { error: 'filreader_not_support_'+as });
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function _isRegularFile(file, callback){
							 | 
						||
| 
								 | 
							
										// http://stackoverflow.com/questions/8856628/detecting-folders-directories-in-javascript-filelist-objects
							 | 
						||
| 
								 | 
							
										if( !file.type && (file.size % 4096) === 0 && (file.size <= 102400) ){
							 | 
						||
| 
								 | 
							
											if( FileReader ){
							 | 
						||
| 
								 | 
							
												try {
							 | 
						||
| 
								 | 
							
													var Reader = new FileReader();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													_one(Reader, _readerEvents, function (evt){
							 | 
						||
| 
								 | 
							
														var isFile = evt.type != 'error';
							 | 
						||
| 
								 | 
							
														callback(isFile);
							 | 
						||
| 
								 | 
							
														if( isFile ){
							 | 
						||
| 
								 | 
							
															Reader.abort();
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													Reader.readAsDataURL(file);
							 | 
						||
| 
								 | 
							
												} catch( err ){
							 | 
						||
| 
								 | 
							
													callback(false);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else {
							 | 
						||
| 
								 | 
							
												callback(null);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else {
							 | 
						||
| 
								 | 
							
											callback(true);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function _getAsEntry(item){
							 | 
						||
| 
								 | 
							
										var entry;
							 | 
						||
| 
								 | 
							
										if( item.getAsEntry ){ entry = item.getAsEntry(); }
							 | 
						||
| 
								 | 
							
										else if( item.webkitGetAsEntry ){ entry = item.webkitGetAsEntry(); }
							 | 
						||
| 
								 | 
							
										return	entry;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function _readEntryAsFiles(entry, callback){
							 | 
						||
| 
								 | 
							
										if( !entry ){
							 | 
						||
| 
								 | 
							
											// error
							 | 
						||
| 
								 | 
							
											callback('invalid entry');
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else if( entry.isFile ){
							 | 
						||
| 
								 | 
							
											// Read as file
							 | 
						||
| 
								 | 
							
											entry.file(function(file){
							 | 
						||
| 
								 | 
							
												// success
							 | 
						||
| 
								 | 
							
												file.fullPath = entry.fullPath;
							 | 
						||
| 
								 | 
							
												callback(false, [file]);
							 | 
						||
| 
								 | 
							
											}, function (err){
							 | 
						||
| 
								 | 
							
												// error
							 | 
						||
| 
								 | 
							
												callback('FileError.code: '+err.code);
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else if( entry.isDirectory ){
							 | 
						||
| 
								 | 
							
											var reader = entry.createReader(), result = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											reader.readEntries(function(entries){
							 | 
						||
| 
								 | 
							
												// success
							 | 
						||
| 
								 | 
							
												api.afor(entries, function (next, entry){
							 | 
						||
| 
								 | 
							
													_readEntryAsFiles(entry, function (err, files){
							 | 
						||
| 
								 | 
							
														if( err ){
							 | 
						||
| 
								 | 
							
															api.log(err);
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
														else {
							 | 
						||
| 
								 | 
							
															result = result.concat(files);
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														if( next ){
							 | 
						||
| 
								 | 
							
															next();
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
														else {
							 | 
						||
| 
								 | 
							
															callback(false, result);
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													});
							 | 
						||
| 
								 | 
							
												});
							 | 
						||
| 
								 | 
							
											}, function (err){
							 | 
						||
| 
								 | 
							
												// error
							 | 
						||
| 
								 | 
							
												callback('directory_reader: ' + err);
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else {
							 | 
						||
| 
								 | 
							
											_readEntryAsFiles(_getAsEntry(entry), callback);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function _simpleClone(obj){
							 | 
						||
| 
								 | 
							
										var copy = {};
							 | 
						||
| 
								 | 
							
										_each(obj, function (val, key){
							 | 
						||
| 
								 | 
							
											if( val && (typeof val === 'object') && (val.nodeType === void 0) ){
							 | 
						||
| 
								 | 
							
												val = _extend({}, val);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											copy[key] = val;
							 | 
						||
| 
								 | 
							
										});
							 | 
						||
| 
								 | 
							
										return	copy;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function isInputFile(el){
							 | 
						||
| 
								 | 
							
										return	_rinput.test(el && el.tagName);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function _getDataTransfer(evt){
							 | 
						||
| 
								 | 
							
										return	(evt.originalEvent || evt || '').dataTransfer || {};
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function _isOriginTransform(trans){
							 | 
						||
| 
								 | 
							
										var key;
							 | 
						||
| 
								 | 
							
										for( key in trans ){
							 | 
						||
| 
								 | 
							
											if( trans.hasOwnProperty(key) ){
							 | 
						||
| 
								 | 
							
												if( !(trans[key] instanceof Object || key === 'overlay' || key === 'filter') ){
							 | 
						||
| 
								 | 
							
													return	true;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return	false;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Add default image info reader
							 | 
						||
| 
								 | 
							
									api.addInfoReader(/^image/, function (file/**File*/, callback/**Function*/){
							 | 
						||
| 
								 | 
							
										if( !file.__dimensions ){
							 | 
						||
| 
								 | 
							
											var defer = file.__dimensions = api.defer();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											api.readAsImage(file, function (evt){
							 | 
						||
| 
								 | 
							
												var img = evt.target;
							 | 
						||
| 
								 | 
							
												defer.resolve(evt.type == 'load' ? false : 'error', {
							 | 
						||
| 
								 | 
							
													  width:  img.width
							 | 
						||
| 
								 | 
							
													, height: img.height
							 | 
						||
| 
								 | 
							
												});
							 | 
						||
| 
								 | 
							
								                img.src = api.EMPTY_PNG;
							 | 
						||
| 
								 | 
							
												img = null;
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										file.__dimensions.then(callback);
							 | 
						||
| 
								 | 
							
									});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Drag'n'Drop special event
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param	{HTMLElement}	el
							 | 
						||
| 
								 | 
							
									 * @param	{Function}		onHover
							 | 
						||
| 
								 | 
							
									 * @param	{Function}		onDrop
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									api.event.dnd = function (el, onHover, onDrop){
							 | 
						||
| 
								 | 
							
										var _id, _type;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if( !onDrop ){
							 | 
						||
| 
								 | 
							
											onDrop = onHover;
							 | 
						||
| 
								 | 
							
											onHover = api.F;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if( FileReader ){
							 | 
						||
| 
								 | 
							
											// Hover
							 | 
						||
| 
								 | 
							
											_on(el, 'dragenter dragleave dragover', onHover.ff = onHover.ff || function (evt){
							 | 
						||
| 
								 | 
							
												var
							 | 
						||
| 
								 | 
							
													  types = _getDataTransfer(evt).types
							 | 
						||
| 
								 | 
							
													, i = types && types.length
							 | 
						||
| 
								 | 
							
													, debounceTrigger = false
							 | 
						||
| 
								 | 
							
												;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												while( i-- ){
							 | 
						||
| 
								 | 
							
													if( ~types[i].indexOf('File') ){
							 | 
						||
| 
								 | 
							
														evt[preventDefault]();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														if( _type !== evt.type ){
							 | 
						||
| 
								 | 
							
															_type = evt.type; // Store current type of event
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															if( _type != 'dragleave' ){
							 | 
						||
| 
								 | 
							
																onHover.call(evt[currentTarget], true, evt);
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															debounceTrigger = true;
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														break; // exit from "while"
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( debounceTrigger ){
							 | 
						||
| 
								 | 
							
													clearTimeout(_id);
							 | 
						||
| 
								 | 
							
													_id = setTimeout(function (){
							 | 
						||
| 
								 | 
							
														onHover.call(evt[currentTarget], _type != 'dragleave', evt);
							 | 
						||
| 
								 | 
							
													}, 50);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Drop
							 | 
						||
| 
								 | 
							
											_on(el, 'drop', onDrop.ff = onDrop.ff || function (evt){
							 | 
						||
| 
								 | 
							
												evt[preventDefault]();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												_type = 0;
							 | 
						||
| 
								 | 
							
												onHover.call(evt[currentTarget], false, evt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												api.getDropFiles(evt, function (files){
							 | 
						||
| 
								 | 
							
													onDrop.call(evt[currentTarget], files, evt);
							 | 
						||
| 
								 | 
							
												});
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else {
							 | 
						||
| 
								 | 
							
											api.log("Drag'n'Drop -- not supported");
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Remove drag'n'drop
							 | 
						||
| 
								 | 
							
									 * @param	{HTMLElement}	el
							 | 
						||
| 
								 | 
							
									 * @param	{Function}		onHover
							 | 
						||
| 
								 | 
							
									 * @param	{Function}		onDrop
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									api.event.dnd.off = function (el, onHover, onDrop){
							 | 
						||
| 
								 | 
							
										_off(el, 'dragenter dragleave dragover', onHover.ff);
							 | 
						||
| 
								 | 
							
										_off(el, 'drop', onDrop.ff);
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Support jQuery
							 | 
						||
| 
								 | 
							
									if( jQuery && !jQuery.fn.dnd ){
							 | 
						||
| 
								 | 
							
										jQuery.fn.dnd = function (onHover, onDrop){
							 | 
						||
| 
								 | 
							
											return this.each(function (){
							 | 
						||
| 
								 | 
							
												api.event.dnd(this, onHover, onDrop);
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
										};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										jQuery.fn.offdnd = function (onHover, onDrop){
							 | 
						||
| 
								 | 
							
											return this.each(function (){
							 | 
						||
| 
								 | 
							
												api.event.dnd.off(this, onHover, onDrop);
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
										};
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// @export
							 | 
						||
| 
								 | 
							
									window.FileAPI  = _extend(api, window.FileAPI);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Debug info
							 | 
						||
| 
								 | 
							
									api.log('FileAPI: ' + api.version);
							 | 
						||
| 
								 | 
							
									api.log('protocol: ' + window.location.protocol);
							 | 
						||
| 
								 | 
							
									api.log('doctype: [' + doctype.name + '] ' + doctype.publicId + ' ' + doctype.systemId);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// @detect 'x-ua-compatible'
							 | 
						||
| 
								 | 
							
									_each(document.getElementsByTagName('meta'), function (meta){
							 | 
						||
| 
								 | 
							
										if( /x-ua-compatible/i.test(meta.getAttribute('http-equiv')) ){
							 | 
						||
| 
								 | 
							
											api.log('meta.http-equiv: ' + meta.getAttribute('content'));
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// @configuration
							 | 
						||
| 
								 | 
							
									if( !api.flashUrl ){ api.flashUrl = api.staticPath + 'FileAPI.flash.swf'; }
							 | 
						||
| 
								 | 
							
									if( !api.flashImageUrl ){ api.flashImageUrl = api.staticPath + 'FileAPI.flash.image.swf'; }
							 | 
						||
| 
								 | 
							
									if( !api.flashWebcamUrl ){ api.flashWebcamUrl = api.staticPath + 'FileAPI.flash.camera.swf'; }
							 | 
						||
| 
								 | 
							
								})(window, void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*global window, FileAPI, document */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(function (api, document, undef) {
							 | 
						||
| 
								 | 
							
									'use strict';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									var
							 | 
						||
| 
								 | 
							
										min = Math.min,
							 | 
						||
| 
								 | 
							
										round = Math.round,
							 | 
						||
| 
								 | 
							
										getCanvas = function () { return document.createElement('canvas'); },
							 | 
						||
| 
								 | 
							
										support = false,
							 | 
						||
| 
								 | 
							
										exifOrientation = {
							 | 
						||
| 
								 | 
							
											  8:	270
							 | 
						||
| 
								 | 
							
											, 3:	180
							 | 
						||
| 
								 | 
							
											, 6:	90
							 | 
						||
| 
								 | 
							
											, 7:	270
							 | 
						||
| 
								 | 
							
											, 4:	180
							 | 
						||
| 
								 | 
							
											, 5:	90
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									try {
							 | 
						||
| 
								 | 
							
										support = getCanvas().toDataURL('image/png').indexOf('data:image/png') > -1;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									catch (e){}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function Image(file){
							 | 
						||
| 
								 | 
							
										if( file instanceof Image ){
							 | 
						||
| 
								 | 
							
											var img = new Image(file.file);
							 | 
						||
| 
								 | 
							
											api.extend(img.matrix, file.matrix);
							 | 
						||
| 
								 | 
							
											return	img;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else if( !(this instanceof Image) ){
							 | 
						||
| 
								 | 
							
											return	new Image(file);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.file   = file;
							 | 
						||
| 
								 | 
							
										this.size   = file.size || 100;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.matrix	= {
							 | 
						||
| 
								 | 
							
											sx: 0,
							 | 
						||
| 
								 | 
							
											sy: 0,
							 | 
						||
| 
								 | 
							
											sw: 0,
							 | 
						||
| 
								 | 
							
											sh: 0,
							 | 
						||
| 
								 | 
							
											dx: 0,
							 | 
						||
| 
								 | 
							
											dy: 0,
							 | 
						||
| 
								 | 
							
											dw: 0,
							 | 
						||
| 
								 | 
							
											dh: 0,
							 | 
						||
| 
								 | 
							
											resize: 0, // min, max OR preview
							 | 
						||
| 
								 | 
							
											deg: 0,
							 | 
						||
| 
								 | 
							
											quality: 1, // jpeg quality
							 | 
						||
| 
								 | 
							
											filter: 0
							 | 
						||
| 
								 | 
							
										};
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									Image.prototype = {
							 | 
						||
| 
								 | 
							
										image: true,
							 | 
						||
| 
								 | 
							
										constructor: Image,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										set: function (attrs){
							 | 
						||
| 
								 | 
							
											api.extend(this.matrix, attrs);
							 | 
						||
| 
								 | 
							
											return	this;
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										crop: function (x, y, w, h){
							 | 
						||
| 
								 | 
							
											if( w === undef ){
							 | 
						||
| 
								 | 
							
												w	= x;
							 | 
						||
| 
								 | 
							
												h	= y;
							 | 
						||
| 
								 | 
							
												x = y = 0;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											return	this.set({ sx: x, sy: y, sw: w, sh: h || w });
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										resize: function (w, h, strategy){
							 | 
						||
| 
								 | 
							
											if( /min|max/.test(h) ){
							 | 
						||
| 
								 | 
							
												strategy = h;
							 | 
						||
| 
								 | 
							
												h = w;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											return	this.set({ dw: w, dh: h || w, resize: strategy });
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										preview: function (w, h){
							 | 
						||
| 
								 | 
							
											return	this.resize(w, h || w, 'preview');
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										rotate: function (deg){
							 | 
						||
| 
								 | 
							
											return	this.set({ deg: deg });
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										filter: function (filter){
							 | 
						||
| 
								 | 
							
											return	this.set({ filter: filter });
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										overlay: function (images){
							 | 
						||
| 
								 | 
							
											return	this.set({ overlay: images });
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										clone: function (){
							 | 
						||
| 
								 | 
							
											return	new Image(this);
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										_load: function (image, fn){
							 | 
						||
| 
								 | 
							
											var self = this;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if( /img|video/i.test(image.nodeName) ){
							 | 
						||
| 
								 | 
							
												fn.call(self, null, image);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else {
							 | 
						||
| 
								 | 
							
												api.readAsImage(image, function (evt){
							 | 
						||
| 
								 | 
							
													fn.call(self, evt.type != 'load', evt.result);
							 | 
						||
| 
								 | 
							
												});
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										_apply: function (image, fn){
							 | 
						||
| 
								 | 
							
											var
							 | 
						||
| 
								 | 
							
												  canvas = getCanvas()
							 | 
						||
| 
								 | 
							
												, m = this.getMatrix(image)
							 | 
						||
| 
								 | 
							
												, ctx = canvas.getContext('2d')
							 | 
						||
| 
								 | 
							
												, width = image.videoWidth || image.width
							 | 
						||
| 
								 | 
							
												, height = image.videoHeight || image.height
							 | 
						||
| 
								 | 
							
												, deg = m.deg
							 | 
						||
| 
								 | 
							
												, dw = m.dw
							 | 
						||
| 
								 | 
							
												, dh = m.dh
							 | 
						||
| 
								 | 
							
												, w = width
							 | 
						||
| 
								 | 
							
												, h = height
							 | 
						||
| 
								 | 
							
												, filter = m.filter
							 | 
						||
| 
								 | 
							
												, copy // canvas copy
							 | 
						||
| 
								 | 
							
												, buffer = image
							 | 
						||
| 
								 | 
							
												, overlay = m.overlay
							 | 
						||
| 
								 | 
							
												, queue = api.queue(function (){ image.src = api.EMPTY_PNG; fn(false, canvas); })
							 | 
						||
| 
								 | 
							
												, renderImageToCanvas = api.renderImageToCanvas
							 | 
						||
| 
								 | 
							
											;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Normalize angle
							 | 
						||
| 
								 | 
							
											deg = deg - Math.floor(deg/360)*360;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// For `renderImageToCanvas`
							 | 
						||
| 
								 | 
							
											image._type = this.file.type;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											while(m.multipass && min(w/dw, h/dh) > 2 ){
							 | 
						||
| 
								 | 
							
												w = (w/2 + 0.5)|0;
							 | 
						||
| 
								 | 
							
												h = (h/2 + 0.5)|0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												copy = getCanvas();
							 | 
						||
| 
								 | 
							
												copy.width  = w;
							 | 
						||
| 
								 | 
							
												copy.height = h;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( buffer !== image ){
							 | 
						||
| 
								 | 
							
													renderImageToCanvas(copy, buffer, 0, 0, buffer.width, buffer.height, 0, 0, w, h);
							 | 
						||
| 
								 | 
							
													buffer = copy;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else {
							 | 
						||
| 
								 | 
							
													buffer = copy;
							 | 
						||
| 
								 | 
							
													renderImageToCanvas(buffer, image, m.sx, m.sy, m.sw, m.sh, 0, 0, w, h);
							 | 
						||
| 
								 | 
							
													m.sx = m.sy = m.sw = m.sh = 0;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											canvas.width  = (deg % 180) ? dh : dw;
							 | 
						||
| 
								 | 
							
											canvas.height = (deg % 180) ? dw : dh;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											canvas.type = m.type;
							 | 
						||
| 
								 | 
							
											canvas.quality = m.quality;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											ctx.rotate(deg * Math.PI / 180);
							 | 
						||
| 
								 | 
							
											renderImageToCanvas(ctx.canvas, buffer
							 | 
						||
| 
								 | 
							
												, m.sx, m.sy
							 | 
						||
| 
								 | 
							
												, m.sw || buffer.width
							 | 
						||
| 
								 | 
							
												, m.sh || buffer.height
							 | 
						||
| 
								 | 
							
												, (deg == 180 || deg == 270 ? -dw : 0)
							 | 
						||
| 
								 | 
							
												, (deg == 90 || deg == 180 ? -dh : 0)
							 | 
						||
| 
								 | 
							
												, dw, dh
							 | 
						||
| 
								 | 
							
											);
							 | 
						||
| 
								 | 
							
											dw = canvas.width;
							 | 
						||
| 
								 | 
							
											dh = canvas.height;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Apply overlay
							 | 
						||
| 
								 | 
							
											overlay && api.each([].concat(overlay), function (over){
							 | 
						||
| 
								 | 
							
												queue.inc();
							 | 
						||
| 
								 | 
							
												// preload
							 | 
						||
| 
								 | 
							
												var img = new window.Image, fn = function (){
							 | 
						||
| 
								 | 
							
													var
							 | 
						||
| 
								 | 
							
														  x = over.x|0
							 | 
						||
| 
								 | 
							
														, y = over.y|0
							 | 
						||
| 
								 | 
							
														, w = over.w || img.width
							 | 
						||
| 
								 | 
							
														, h = over.h || img.height
							 | 
						||
| 
								 | 
							
														, rel = over.rel
							 | 
						||
| 
								 | 
							
													;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													// center  |  right  |  left
							 | 
						||
| 
								 | 
							
													x = (rel == 1 || rel == 4 || rel == 7) ? (dw - w + x)/2 : (rel == 2 || rel == 5 || rel == 8 ? dw - (w + x) : x);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													// center  |  bottom  |  top
							 | 
						||
| 
								 | 
							
													y = (rel == 3 || rel == 4 || rel == 5) ? (dh - h + y)/2 : (rel >= 6 ? dh - (h + y) : y);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													api.event.off(img, 'error load abort', fn);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													try {
							 | 
						||
| 
								 | 
							
														ctx.globalAlpha = over.opacity || 1;
							 | 
						||
| 
								 | 
							
														ctx.drawImage(img, x, y, w, h);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													catch (er){}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													queue.next();
							 | 
						||
| 
								 | 
							
												};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												api.event.on(img, 'error load abort', fn);
							 | 
						||
| 
								 | 
							
												img.src = over.src;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( img.complete ){
							 | 
						||
| 
								 | 
							
													fn();
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if( filter ){
							 | 
						||
| 
								 | 
							
												queue.inc();
							 | 
						||
| 
								 | 
							
												Image.applyFilter(canvas, filter, queue.next);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											queue.check();
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										getMatrix: function (image){
							 | 
						||
| 
								 | 
							
											var
							 | 
						||
| 
								 | 
							
												  m  = api.extend({}, this.matrix)
							 | 
						||
| 
								 | 
							
												, sw = m.sw = m.sw || image.videoWidth || image.naturalWidth ||  image.width
							 | 
						||
| 
								 | 
							
												, sh = m.sh = m.sh || image.videoHeight || image.naturalHeight || image.height
							 | 
						||
| 
								 | 
							
												, dw = m.dw = m.dw || sw
							 | 
						||
| 
								 | 
							
												, dh = m.dh = m.dh || sh
							 | 
						||
| 
								 | 
							
												, sf = sw/sh, df = dw/dh
							 | 
						||
| 
								 | 
							
												, strategy = m.resize
							 | 
						||
| 
								 | 
							
											;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if( strategy == 'preview' ){
							 | 
						||
| 
								 | 
							
												if( dw != sw || dh != sh ){
							 | 
						||
| 
								 | 
							
													// Make preview
							 | 
						||
| 
								 | 
							
													var w, h;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													if( df >= sf ){
							 | 
						||
| 
								 | 
							
														w	= sw;
							 | 
						||
| 
								 | 
							
														h	= w / df;
							 | 
						||
| 
								 | 
							
													} else {
							 | 
						||
| 
								 | 
							
														h	= sh;
							 | 
						||
| 
								 | 
							
														w	= h * df;
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													if( w != sw || h != sh ){
							 | 
						||
| 
								 | 
							
														m.sx	= ~~((sw - w)/2);
							 | 
						||
| 
								 | 
							
														m.sy	= ~~((sh - h)/2);
							 | 
						||
| 
								 | 
							
														sw		= w;
							 | 
						||
| 
								 | 
							
														sh		= h;
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else if( strategy ){
							 | 
						||
| 
								 | 
							
												if( !(sw > dw || sh > dh) ){
							 | 
						||
| 
								 | 
							
													dw = sw;
							 | 
						||
| 
								 | 
							
													dh = sh;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else if( strategy == 'min' ){
							 | 
						||
| 
								 | 
							
													dw = round(sf < df ? min(sw, dw) : dh*sf);
							 | 
						||
| 
								 | 
							
													dh = round(sf < df ? dw/sf : min(sh, dh));
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else {
							 | 
						||
| 
								 | 
							
													dw = round(sf >= df ? min(sw, dw) : dh*sf);
							 | 
						||
| 
								 | 
							
													dh = round(sf >= df ? dw/sf : min(sh, dh));
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											m.sw = sw;
							 | 
						||
| 
								 | 
							
											m.sh = sh;
							 | 
						||
| 
								 | 
							
											m.dw = dw;
							 | 
						||
| 
								 | 
							
											m.dh = dh;
							 | 
						||
| 
								 | 
							
											m.multipass = api.multiPassResize;
							 | 
						||
| 
								 | 
							
											return	m;
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										_trans: function (fn){
							 | 
						||
| 
								 | 
							
											this._load(this.file, function (err, image){
							 | 
						||
| 
								 | 
							
												if( err ){
							 | 
						||
| 
								 | 
							
													fn(err);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else {
							 | 
						||
| 
								 | 
							
													try {
							 | 
						||
| 
								 | 
							
														this._apply(image, fn);
							 | 
						||
| 
								 | 
							
													} catch (err){
							 | 
						||
| 
								 | 
							
														api.log('[err] FileAPI.Image.fn._apply:', err);
							 | 
						||
| 
								 | 
							
														fn(err);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										get: function (fn){
							 | 
						||
| 
								 | 
							
											if( api.support.transform ){
							 | 
						||
| 
								 | 
							
												var _this = this, matrix = _this.matrix;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( matrix.deg == 'auto' ){
							 | 
						||
| 
								 | 
							
													api.getInfo(_this.file, function (err, info){
							 | 
						||
| 
								 | 
							
														// rotate by exif orientation
							 | 
						||
| 
								 | 
							
														matrix.deg = exifOrientation[info && info.exif && info.exif.Orientation] || 0;
							 | 
						||
| 
								 | 
							
														_this._trans(fn);
							 | 
						||
| 
								 | 
							
													});
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else {
							 | 
						||
| 
								 | 
							
													_this._trans(fn);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else {
							 | 
						||
| 
								 | 
							
												fn('not_support_transform');
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											return this;
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										toData: function (fn){
							 | 
						||
| 
								 | 
							
											return this.get(fn);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									Image.exifOrientation = exifOrientation;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									Image.transform = function (file, transform, autoOrientation, fn){
							 | 
						||
| 
								 | 
							
										function _transform(err, img){
							 | 
						||
| 
								 | 
							
											// img -- info object
							 | 
						||
| 
								 | 
							
											var
							 | 
						||
| 
								 | 
							
												  images = {}
							 | 
						||
| 
								 | 
							
												, queue = api.queue(function (err){
							 | 
						||
| 
								 | 
							
													fn(err, images);
							 | 
						||
| 
								 | 
							
												})
							 | 
						||
| 
								 | 
							
											;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if( !err ){
							 | 
						||
| 
								 | 
							
												api.each(transform, function (params, name){
							 | 
						||
| 
								 | 
							
													if( !queue.isFail() ){
							 | 
						||
| 
								 | 
							
														var ImgTrans = new Image(img.nodeType ? img : file), isFn = typeof params == 'function';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														if( isFn ){
							 | 
						||
| 
								 | 
							
															params(img, ImgTrans);
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
														else if( params.width ){
							 | 
						||
| 
								 | 
							
															ImgTrans[params.preview ? 'preview' : 'resize'](params.width, params.height, params.strategy);
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
														else {
							 | 
						||
| 
								 | 
							
															if( params.maxWidth && (img.width > params.maxWidth || img.height > params.maxHeight) ){
							 | 
						||
| 
								 | 
							
																ImgTrans.resize(params.maxWidth, params.maxHeight, 'max');
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														if( params.crop ){
							 | 
						||
| 
								 | 
							
															var crop = params.crop;
							 | 
						||
| 
								 | 
							
															ImgTrans.crop(crop.x|0, crop.y|0, crop.w || crop.width, crop.h || crop.height);
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														if( params.rotate === undef && autoOrientation ){
							 | 
						||
| 
								 | 
							
															params.rotate = 'auto';
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														ImgTrans.set({ type: ImgTrans.matrix.type || params.type || file.type || 'image/png' });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														if( !isFn ){
							 | 
						||
| 
								 | 
							
															ImgTrans.set({
							 | 
						||
| 
								 | 
							
																  deg: params.rotate
							 | 
						||
| 
								 | 
							
																, overlay: params.overlay
							 | 
						||
| 
								 | 
							
																, filter: params.filter
							 | 
						||
| 
								 | 
							
																, quality: params.quality || 1
							 | 
						||
| 
								 | 
							
															});
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														queue.inc();
							 | 
						||
| 
								 | 
							
														ImgTrans.toData(function (err, image){
							 | 
						||
| 
								 | 
							
															if( err ){
							 | 
						||
| 
								 | 
							
																queue.fail();
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
															else {
							 | 
						||
| 
								 | 
							
																images[name] = image;
							 | 
						||
| 
								 | 
							
																queue.next();
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
														});
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												});
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else {
							 | 
						||
| 
								 | 
							
												queue.fail();
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// @todo: Оло-ло, нужно рефакторить это место
							 | 
						||
| 
								 | 
							
										if( file.width ){
							 | 
						||
| 
								 | 
							
											_transform(false, file);
							 | 
						||
| 
								 | 
							
										} else {
							 | 
						||
| 
								 | 
							
											api.getInfo(file, _transform);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// @const
							 | 
						||
| 
								 | 
							
									api.each(['TOP', 'CENTER', 'BOTTOM'], function (x, i){
							 | 
						||
| 
								 | 
							
										api.each(['LEFT', 'CENTER', 'RIGHT'], function (y, j){
							 | 
						||
| 
								 | 
							
											Image[x+'_'+y] = i*3 + j;
							 | 
						||
| 
								 | 
							
											Image[y+'_'+x] = i*3 + j;
							 | 
						||
| 
								 | 
							
										});
							 | 
						||
| 
								 | 
							
									});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Trabsform element to canvas
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param    {Image|HTMLVideoElement}   el
							 | 
						||
| 
								 | 
							
									 * @returns  {Canvas}
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									Image.toCanvas = function(el){
							 | 
						||
| 
								 | 
							
										var canvas		= document.createElement('canvas');
							 | 
						||
| 
								 | 
							
										canvas.width	= el.videoWidth || el.width;
							 | 
						||
| 
								 | 
							
										canvas.height	= el.videoHeight || el.height;
							 | 
						||
| 
								 | 
							
										canvas.getContext('2d').drawImage(el, 0, 0);
							 | 
						||
| 
								 | 
							
										return	canvas;
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Create image from DataURL
							 | 
						||
| 
								 | 
							
									 * @param  {String}  dataURL
							 | 
						||
| 
								 | 
							
									 * @param  {Object}  size
							 | 
						||
| 
								 | 
							
									 * @param  {Function}  callback
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									Image.fromDataURL = function (dataURL, size, callback){
							 | 
						||
| 
								 | 
							
										var img = api.newImage(dataURL);
							 | 
						||
| 
								 | 
							
										api.extend(img, size);
							 | 
						||
| 
								 | 
							
										callback(img);
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Apply filter (caman.js)
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param  {Canvas|Image}   canvas
							 | 
						||
| 
								 | 
							
									 * @param  {String|Function}  filter
							 | 
						||
| 
								 | 
							
									 * @param  {Function}  doneFn
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									Image.applyFilter = function (canvas, filter, doneFn){
							 | 
						||
| 
								 | 
							
										if( typeof filter == 'function' ){
							 | 
						||
| 
								 | 
							
											filter(canvas, doneFn);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else if( window.Caman ){
							 | 
						||
| 
								 | 
							
											// http://camanjs.com/guides/
							 | 
						||
| 
								 | 
							
											window.Caman(canvas.tagName == 'IMG' ? Image.toCanvas(canvas) : canvas, function (){
							 | 
						||
| 
								 | 
							
												if( typeof filter == 'string' ){
							 | 
						||
| 
								 | 
							
													this[filter]();
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else {
							 | 
						||
| 
								 | 
							
													api.each(filter, function (val, method){
							 | 
						||
| 
								 | 
							
														this[method](val);
							 | 
						||
| 
								 | 
							
													}, this);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												this.render(doneFn);
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * For load-image-ios.js
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									api.renderImageToCanvas = function (canvas, img, sx, sy, sw, sh, dx, dy, dw, dh){
							 | 
						||
| 
								 | 
							
										try {
							 | 
						||
| 
								 | 
							
											return canvas.getContext('2d').drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh);
							 | 
						||
| 
								 | 
							
										} catch (ex) {
							 | 
						||
| 
								 | 
							
											api.log('renderImageToCanvas failed');
							 | 
						||
| 
								 | 
							
											throw ex;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// @export
							 | 
						||
| 
								 | 
							
									api.support.canvas = api.support.transform = support;
							 | 
						||
| 
								 | 
							
									api.Image = Image;
							 | 
						||
| 
								 | 
							
								})(FileAPI, document);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * JavaScript Load Image iOS scaling fixes 1.0.3
							 | 
						||
| 
								 | 
							
								 * https://github.com/blueimp/JavaScript-Load-Image
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Copyright 2013, Sebastian Tschan
							 | 
						||
| 
								 | 
							
								 * https://blueimp.net
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * iOS image scaling fixes based on
							 | 
						||
| 
								 | 
							
								 * https://github.com/stomita/ios-imagefile-megapixel
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Licensed under the MIT license:
							 | 
						||
| 
								 | 
							
								 * http://www.opensource.org/licenses/MIT
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*jslint nomen: true, bitwise: true */
							 | 
						||
| 
								 | 
							
								/*global FileAPI, window, document */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(function (factory) {
							 | 
						||
| 
								 | 
							
									'use strict';
							 | 
						||
| 
								 | 
							
									factory(FileAPI);
							 | 
						||
| 
								 | 
							
								}(function (loadImage) {
							 | 
						||
| 
								 | 
							
								    'use strict';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Only apply fixes on the iOS platform:
							 | 
						||
| 
								 | 
							
								    if (!window.navigator || !window.navigator.platform ||
							 | 
						||
| 
								 | 
							
								             !(/iP(hone|od|ad)/).test(window.navigator.platform)) {
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    var originalRenderMethod = loadImage.renderImageToCanvas;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Detects subsampling in JPEG images:
							 | 
						||
| 
								 | 
							
								    loadImage.detectSubsampling = function (img) {
							 | 
						||
| 
								 | 
							
								        var canvas,
							 | 
						||
| 
								 | 
							
								            context;
							 | 
						||
| 
								 | 
							
								        if (img.width * img.height > 1024 * 1024) { // only consider mexapixel images
							 | 
						||
| 
								 | 
							
								            canvas = document.createElement('canvas');
							 | 
						||
| 
								 | 
							
								            canvas.width = canvas.height = 1;
							 | 
						||
| 
								 | 
							
								            context = canvas.getContext('2d');
							 | 
						||
| 
								 | 
							
								            context.drawImage(img, -img.width + 1, 0);
							 | 
						||
| 
								 | 
							
								            // subsampled image becomes half smaller in rendering size.
							 | 
						||
| 
								 | 
							
								            // check alpha channel value to confirm image is covering edge pixel or not.
							 | 
						||
| 
								 | 
							
								            // if alpha value is 0 image is not covering, hence subsampled.
							 | 
						||
| 
								 | 
							
								            return context.getImageData(0, 0, 1, 1).data[3] === 0;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return false;
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Detects vertical squash in JPEG images:
							 | 
						||
| 
								 | 
							
								    loadImage.detectVerticalSquash = function (img, subsampled) {
							 | 
						||
| 
								 | 
							
								        var naturalHeight = img.naturalHeight || img.height,
							 | 
						||
| 
								 | 
							
								            canvas = document.createElement('canvas'),
							 | 
						||
| 
								 | 
							
								            context = canvas.getContext('2d'),
							 | 
						||
| 
								 | 
							
								            data,
							 | 
						||
| 
								 | 
							
								            sy,
							 | 
						||
| 
								 | 
							
								            ey,
							 | 
						||
| 
								 | 
							
								            py,
							 | 
						||
| 
								 | 
							
								            alpha;
							 | 
						||
| 
								 | 
							
								        if (subsampled) {
							 | 
						||
| 
								 | 
							
								            naturalHeight /= 2;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        canvas.width = 1;
							 | 
						||
| 
								 | 
							
								        canvas.height = naturalHeight;
							 | 
						||
| 
								 | 
							
								        context.drawImage(img, 0, 0);
							 | 
						||
| 
								 | 
							
								        data = context.getImageData(0, 0, 1, naturalHeight).data;
							 | 
						||
| 
								 | 
							
								        // search image edge pixel position in case it is squashed vertically:
							 | 
						||
| 
								 | 
							
								        sy = 0;
							 | 
						||
| 
								 | 
							
								        ey = naturalHeight;
							 | 
						||
| 
								 | 
							
								        py = naturalHeight;
							 | 
						||
| 
								 | 
							
								        while (py > sy) {
							 | 
						||
| 
								 | 
							
								            alpha = data[(py - 1) * 4 + 3];
							 | 
						||
| 
								 | 
							
								            if (alpha === 0) {
							 | 
						||
| 
								 | 
							
								                ey = py;
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                sy = py;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            py = (ey + sy) >> 1;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return (py / naturalHeight) || 1;
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Renders image to canvas while working around iOS image scaling bugs:
							 | 
						||
| 
								 | 
							
								    // https://github.com/blueimp/JavaScript-Load-Image/issues/13
							 | 
						||
| 
								 | 
							
								    loadImage.renderImageToCanvas = function (
							 | 
						||
| 
								 | 
							
								        canvas,
							 | 
						||
| 
								 | 
							
								        img,
							 | 
						||
| 
								 | 
							
								        sourceX,
							 | 
						||
| 
								 | 
							
								        sourceY,
							 | 
						||
| 
								 | 
							
								        sourceWidth,
							 | 
						||
| 
								 | 
							
								        sourceHeight,
							 | 
						||
| 
								 | 
							
								        destX,
							 | 
						||
| 
								 | 
							
								        destY,
							 | 
						||
| 
								 | 
							
								        destWidth,
							 | 
						||
| 
								 | 
							
								        destHeight
							 | 
						||
| 
								 | 
							
								    ) {
							 | 
						||
| 
								 | 
							
								        if (img._type === 'image/jpeg') {
							 | 
						||
| 
								 | 
							
								            var context = canvas.getContext('2d'),
							 | 
						||
| 
								 | 
							
								                tmpCanvas = document.createElement('canvas'),
							 | 
						||
| 
								 | 
							
								                tileSize = 1024,
							 | 
						||
| 
								 | 
							
								                tmpContext = tmpCanvas.getContext('2d'),
							 | 
						||
| 
								 | 
							
								                subsampled,
							 | 
						||
| 
								 | 
							
								                vertSquashRatio,
							 | 
						||
| 
								 | 
							
								                tileX,
							 | 
						||
| 
								 | 
							
								                tileY;
							 | 
						||
| 
								 | 
							
								            tmpCanvas.width = tileSize;
							 | 
						||
| 
								 | 
							
								            tmpCanvas.height = tileSize;
							 | 
						||
| 
								 | 
							
								            context.save();
							 | 
						||
| 
								 | 
							
								            subsampled = loadImage.detectSubsampling(img);
							 | 
						||
| 
								 | 
							
								            if (subsampled) {
							 | 
						||
| 
								 | 
							
								                sourceX /= 2;
							 | 
						||
| 
								 | 
							
								                sourceY /= 2;
							 | 
						||
| 
								 | 
							
								                sourceWidth /= 2;
							 | 
						||
| 
								 | 
							
								                sourceHeight /= 2;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            vertSquashRatio = loadImage.detectVerticalSquash(img, subsampled);
							 | 
						||
| 
								 | 
							
								            if (subsampled || vertSquashRatio !== 1) {
							 | 
						||
| 
								 | 
							
								                sourceY *= vertSquashRatio;
							 | 
						||
| 
								 | 
							
								                destWidth = Math.ceil(tileSize * destWidth / sourceWidth);
							 | 
						||
| 
								 | 
							
								                destHeight = Math.ceil(
							 | 
						||
| 
								 | 
							
								                    tileSize * destHeight / sourceHeight / vertSquashRatio
							 | 
						||
| 
								 | 
							
								                );
							 | 
						||
| 
								 | 
							
								                destY = 0;
							 | 
						||
| 
								 | 
							
								                tileY = 0;
							 | 
						||
| 
								 | 
							
								                while (tileY < sourceHeight) {
							 | 
						||
| 
								 | 
							
								                    destX = 0;
							 | 
						||
| 
								 | 
							
								                    tileX = 0;
							 | 
						||
| 
								 | 
							
								                    while (tileX < sourceWidth) {
							 | 
						||
| 
								 | 
							
								                        tmpContext.clearRect(0, 0, tileSize, tileSize);
							 | 
						||
| 
								 | 
							
								                        tmpContext.drawImage(
							 | 
						||
| 
								 | 
							
								                            img,
							 | 
						||
| 
								 | 
							
								                            sourceX,
							 | 
						||
| 
								 | 
							
								                            sourceY,
							 | 
						||
| 
								 | 
							
								                            sourceWidth,
							 | 
						||
| 
								 | 
							
								                            sourceHeight,
							 | 
						||
| 
								 | 
							
								                            -tileX,
							 | 
						||
| 
								 | 
							
								                            -tileY,
							 | 
						||
| 
								 | 
							
								                            sourceWidth,
							 | 
						||
| 
								 | 
							
								                            sourceHeight
							 | 
						||
| 
								 | 
							
								                        );
							 | 
						||
| 
								 | 
							
								                        context.drawImage(
							 | 
						||
| 
								 | 
							
								                            tmpCanvas,
							 | 
						||
| 
								 | 
							
								                            0,
							 | 
						||
| 
								 | 
							
								                            0,
							 | 
						||
| 
								 | 
							
								                            tileSize,
							 | 
						||
| 
								 | 
							
								                            tileSize,
							 | 
						||
| 
								 | 
							
								                            destX,
							 | 
						||
| 
								 | 
							
								                            destY,
							 | 
						||
| 
								 | 
							
								                            destWidth,
							 | 
						||
| 
								 | 
							
								                            destHeight
							 | 
						||
| 
								 | 
							
								                        );
							 | 
						||
| 
								 | 
							
								                        tileX += tileSize;
							 | 
						||
| 
								 | 
							
								                        destX += destWidth;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    tileY += tileSize;
							 | 
						||
| 
								 | 
							
								                    destY += destHeight;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                context.restore();
							 | 
						||
| 
								 | 
							
								                return canvas;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return originalRenderMethod(
							 | 
						||
| 
								 | 
							
								            canvas,
							 | 
						||
| 
								 | 
							
								            img,
							 | 
						||
| 
								 | 
							
								            sourceX,
							 | 
						||
| 
								 | 
							
								            sourceY,
							 | 
						||
| 
								 | 
							
								            sourceWidth,
							 | 
						||
| 
								 | 
							
								            sourceHeight,
							 | 
						||
| 
								 | 
							
								            destX,
							 | 
						||
| 
								 | 
							
								            destY,
							 | 
						||
| 
								 | 
							
								            destWidth,
							 | 
						||
| 
								 | 
							
								            destHeight
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*global window, FileAPI */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(function (api, window){
							 | 
						||
| 
								 | 
							
									"use strict";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									var
							 | 
						||
| 
								 | 
							
										  document = window.document
							 | 
						||
| 
								 | 
							
										, FormData = window.FormData
							 | 
						||
| 
								 | 
							
										, Form = function (){ this.items = []; }
							 | 
						||
| 
								 | 
							
										, encodeURIComponent = window.encodeURIComponent
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									Form.prototype = {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										append: function (name, blob, file, type){
							 | 
						||
| 
								 | 
							
											this.items.push({
							 | 
						||
| 
								 | 
							
												  name: name
							 | 
						||
| 
								 | 
							
												, blob: blob && blob.blob || (blob == void 0 ? '' : blob)
							 | 
						||
| 
								 | 
							
												, file: blob && (file || blob.name)
							 | 
						||
| 
								 | 
							
												, type:	blob && (type || blob.type)
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										each: function (fn){
							 | 
						||
| 
								 | 
							
											var i = 0, n = this.items.length;
							 | 
						||
| 
								 | 
							
											for( ; i < n; i++ ){
							 | 
						||
| 
								 | 
							
												fn.call(this, this.items[i]);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										toData: function (fn, options){
							 | 
						||
| 
								 | 
							
										    // allow chunked transfer if we have only one file to send
							 | 
						||
| 
								 | 
							
										    // flag is used below and in XHR._send
							 | 
						||
| 
								 | 
							
										    options._chunked = api.support.chunked && options.chunkSize > 0 && api.filter(this.items, function (item){ return item.file; }).length == 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if( !api.support.html5 ){
							 | 
						||
| 
								 | 
							
												api.log('FileAPI.Form.toHtmlData');
							 | 
						||
| 
								 | 
							
												this.toHtmlData(fn);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else if( !api.formData || this.multipart || !FormData ){
							 | 
						||
| 
								 | 
							
												api.log('FileAPI.Form.toMultipartData');
							 | 
						||
| 
								 | 
							
												this.toMultipartData(fn);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else if( options._chunked ){
							 | 
						||
| 
								 | 
							
												api.log('FileAPI.Form.toPlainData');
							 | 
						||
| 
								 | 
							
												this.toPlainData(fn);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else {
							 | 
						||
| 
								 | 
							
												api.log('FileAPI.Form.toFormData');
							 | 
						||
| 
								 | 
							
												this.toFormData(fn);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										_to: function (data, complete, next, arg){
							 | 
						||
| 
								 | 
							
											var queue = api.queue(function (){
							 | 
						||
| 
								 | 
							
												complete(data);
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											this.each(function (file){
							 | 
						||
| 
								 | 
							
												next(file, data, queue, arg);
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											queue.check();
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										toHtmlData: function (fn){
							 | 
						||
| 
								 | 
							
											this._to(document.createDocumentFragment(), fn, function (file, data/**DocumentFragment*/){
							 | 
						||
| 
								 | 
							
												var blob = file.blob, hidden;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( file.file ){
							 | 
						||
| 
								 | 
							
													api.reset(blob, true);
							 | 
						||
| 
								 | 
							
													// set new name
							 | 
						||
| 
								 | 
							
													blob.name = file.name;
							 | 
						||
| 
								 | 
							
													blob.disabled = false;
							 | 
						||
| 
								 | 
							
													data.appendChild(blob);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else {
							 | 
						||
| 
								 | 
							
													hidden = document.createElement('input');
							 | 
						||
| 
								 | 
							
													hidden.name  = file.name;
							 | 
						||
| 
								 | 
							
													hidden.type  = 'hidden';
							 | 
						||
| 
								 | 
							
													hidden.value = blob;
							 | 
						||
| 
								 | 
							
													data.appendChild(hidden);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										toPlainData: function (fn){
							 | 
						||
| 
								 | 
							
											this._to({}, fn, function (file, data, queue){
							 | 
						||
| 
								 | 
							
												if( file.file ){
							 | 
						||
| 
								 | 
							
													data.type = file.file;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( file.blob.toBlob ){
							 | 
						||
| 
								 | 
							
												    // canvas
							 | 
						||
| 
								 | 
							
													queue.inc();
							 | 
						||
| 
								 | 
							
													_convertFile(file, function (file, blob){
							 | 
						||
| 
								 | 
							
														data.name = file.name;
							 | 
						||
| 
								 | 
							
														data.file = blob;
							 | 
						||
| 
								 | 
							
														data.size = blob.length;
							 | 
						||
| 
								 | 
							
														data.type = file.type;
							 | 
						||
| 
								 | 
							
														queue.next();
							 | 
						||
| 
								 | 
							
													});
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else if( file.file ){
							 | 
						||
| 
								 | 
							
												    // file
							 | 
						||
| 
								 | 
							
													data.name = file.blob.name;
							 | 
						||
| 
								 | 
							
													data.file = file.blob;
							 | 
						||
| 
								 | 
							
													data.size = file.blob.size;
							 | 
						||
| 
								 | 
							
													data.type = file.type;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else {
							 | 
						||
| 
								 | 
							
												    // additional data
							 | 
						||
| 
								 | 
							
												    if( !data.params ){
							 | 
						||
| 
								 | 
							
												        data.params = [];
							 | 
						||
| 
								 | 
							
												    }
							 | 
						||
| 
								 | 
							
												    data.params.push(encodeURIComponent(file.name) +"="+ encodeURIComponent(file.blob));
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												data.start = -1;
							 | 
						||
| 
								 | 
							
												data.end = data.file && data.file.FileAPIReadPosition || -1;
							 | 
						||
| 
								 | 
							
												data.retry = 0;
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										toFormData: function (fn){
							 | 
						||
| 
								 | 
							
											this._to(new FormData, fn, function (file, data, queue){
							 | 
						||
| 
								 | 
							
												if( file.blob && file.blob.toBlob ){
							 | 
						||
| 
								 | 
							
													queue.inc();
							 | 
						||
| 
								 | 
							
													_convertFile(file, function (file, blob){
							 | 
						||
| 
								 | 
							
														data.append(file.name, blob, file.file);
							 | 
						||
| 
								 | 
							
														queue.next();
							 | 
						||
| 
								 | 
							
													});
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else if( file.file ){
							 | 
						||
| 
								 | 
							
													data.append(file.name, file.blob, file.file);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else {
							 | 
						||
| 
								 | 
							
													data.append(file.name, file.blob);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( file.file ){
							 | 
						||
| 
								 | 
							
													data.append('_'+file.name, file.file);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										toMultipartData: function (fn){
							 | 
						||
| 
								 | 
							
											this._to([], fn, function (file, data, queue, boundary){
							 | 
						||
| 
								 | 
							
												queue.inc();
							 | 
						||
| 
								 | 
							
												_convertFile(file, function (file, blob){
							 | 
						||
| 
								 | 
							
													data.push(
							 | 
						||
| 
								 | 
							
														  '--_' + boundary + ('\r\nContent-Disposition: form-data; name="'+ file.name +'"'+ (file.file ? '; filename="'+ encodeURIComponent(file.file) +'"' : '')
							 | 
						||
| 
								 | 
							
														+ (file.file ? '\r\nContent-Type: '+ (file.type || 'application/octet-stream') : '')
							 | 
						||
| 
								 | 
							
														+ '\r\n'
							 | 
						||
| 
								 | 
							
														+ '\r\n'+ (file.file ? blob : encodeURIComponent(blob))
							 | 
						||
| 
								 | 
							
														+ '\r\n')
							 | 
						||
| 
								 | 
							
													);
							 | 
						||
| 
								 | 
							
													queue.next();
							 | 
						||
| 
								 | 
							
												}, true);
							 | 
						||
| 
								 | 
							
											}, api.expando);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function _convertFile(file, fn, useBinaryString){
							 | 
						||
| 
								 | 
							
										var blob = file.blob, filename = file.file;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if( filename ){
							 | 
						||
| 
								 | 
							
											if( !blob.toDataURL ){
							 | 
						||
| 
								 | 
							
												// The Blob is not an image.
							 | 
						||
| 
								 | 
							
												api.readAsBinaryString(blob, function (evt){
							 | 
						||
| 
								 | 
							
													if( evt.type == 'load' ){
							 | 
						||
| 
								 | 
							
														fn(file, evt.result);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												});
							 | 
						||
| 
								 | 
							
												return;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											var
							 | 
						||
| 
								 | 
							
												  mime = { 'image/jpeg': '.jpe?g', 'image/png': '.png' }
							 | 
						||
| 
								 | 
							
												, type = mime[file.type] ? file.type : 'image/png'
							 | 
						||
| 
								 | 
							
												, ext  = mime[type] || '.png'
							 | 
						||
| 
								 | 
							
												, quality = blob.quality || 1
							 | 
						||
| 
								 | 
							
											;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if( !filename.match(new RegExp(ext+'$', 'i')) ){
							 | 
						||
| 
								 | 
							
												// Does not change the current extension, but add a new one.
							 | 
						||
| 
								 | 
							
												filename += ext.replace('?', '');
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											file.file = filename;
							 | 
						||
| 
								 | 
							
											file.type = type;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if( !useBinaryString && blob.toBlob ){
							 | 
						||
| 
								 | 
							
												blob.toBlob(function (blob){
							 | 
						||
| 
								 | 
							
													fn(file, blob);
							 | 
						||
| 
								 | 
							
												}, type, quality);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else {
							 | 
						||
| 
								 | 
							
												fn(file, api.toBinaryString(blob.toDataURL(type, quality)));
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else {
							 | 
						||
| 
								 | 
							
											fn(file, blob);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// @export
							 | 
						||
| 
								 | 
							
									api.Form = Form;
							 | 
						||
| 
								 | 
							
								})(FileAPI, window);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*global window, FileAPI, Uint8Array */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(function (window, api){
							 | 
						||
| 
								 | 
							
									"use strict";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									var
							 | 
						||
| 
								 | 
							
										  noop = function (){}
							 | 
						||
| 
								 | 
							
										, document = window.document
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										, XHR = function (options){
							 | 
						||
| 
								 | 
							
											this.uid = api.uid();
							 | 
						||
| 
								 | 
							
											this.xhr = {
							 | 
						||
| 
								 | 
							
												  abort: noop
							 | 
						||
| 
								 | 
							
												, getResponseHeader: noop
							 | 
						||
| 
								 | 
							
												, getAllResponseHeaders: noop
							 | 
						||
| 
								 | 
							
											};
							 | 
						||
| 
								 | 
							
											this.options = options;
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										_xhrResponsePostfix = { '': 1, XML: 1, Text: 1, Body: 1 }
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									XHR.prototype = {
							 | 
						||
| 
								 | 
							
										status: 0,
							 | 
						||
| 
								 | 
							
										statusText: '',
							 | 
						||
| 
								 | 
							
										constructor: XHR,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										getResponseHeader: function (name){
							 | 
						||
| 
								 | 
							
											return this.xhr.getResponseHeader(name);
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										getAllResponseHeaders: function (){
							 | 
						||
| 
								 | 
							
											return this.xhr.getAllResponseHeaders() || {};
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										end: function (status, statusText){
							 | 
						||
| 
								 | 
							
											var _this = this, options = _this.options;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											_this.end		=
							 | 
						||
| 
								 | 
							
											_this.abort		= noop;
							 | 
						||
| 
								 | 
							
											_this.status	= status;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if( statusText ){
							 | 
						||
| 
								 | 
							
												_this.statusText = statusText;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											api.log('xhr.end:', status, statusText);
							 | 
						||
| 
								 | 
							
											options.complete(status == 200 || status == 201 ? false : _this.statusText || 'unknown', _this);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if( _this.xhr && _this.xhr.node ){
							 | 
						||
| 
								 | 
							
												setTimeout(function (){
							 | 
						||
| 
								 | 
							
													var node = _this.xhr.node;
							 | 
						||
| 
								 | 
							
													try { node.parentNode.removeChild(node); } catch (e){}
							 | 
						||
| 
								 | 
							
													try { delete window[_this.uid]; } catch (e){}
							 | 
						||
| 
								 | 
							
													window[_this.uid] = _this.xhr.node = null;
							 | 
						||
| 
								 | 
							
												}, 9);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										abort: function (){
							 | 
						||
| 
								 | 
							
											this.end(0, 'abort');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if( this.xhr ){
							 | 
						||
| 
								 | 
							
												this.xhr.aborted = true;
							 | 
						||
| 
								 | 
							
												this.xhr.abort();
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										send: function (FormData){
							 | 
						||
| 
								 | 
							
											var _this = this, options = this.options;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											FormData.toData(function (data){
							 | 
						||
| 
								 | 
							
												// Start uploading
							 | 
						||
| 
								 | 
							
												options.upload(options, _this);
							 | 
						||
| 
								 | 
							
												_this._send.call(_this, options, data);
							 | 
						||
| 
								 | 
							
											}, options);
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										_send: function (options, data){
							 | 
						||
| 
								 | 
							
											var _this = this, xhr, uid = _this.uid, onloadFuncName = _this.uid + "Load", url = options.url;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											api.log('XHR._send:', data);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if( !options.cache ){
							 | 
						||
| 
								 | 
							
												// No cache
							 | 
						||
| 
								 | 
							
												url += (~url.indexOf('?') ? '&' : '?') + api.uid();
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if( data.nodeName ){
							 | 
						||
| 
								 | 
							
												var jsonp = options.jsonp;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// prepare callback in GET
							 | 
						||
| 
								 | 
							
												url = url.replace(/([a-z]+)=(\?)/i, '$1='+uid);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// legacy
							 | 
						||
| 
								 | 
							
												options.upload(options, _this);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												var
							 | 
						||
| 
								 | 
							
													onPostMessage = function (evt){
							 | 
						||
| 
								 | 
							
														if( ~url.indexOf(evt.origin) ){
							 | 
						||
| 
								 | 
							
															try {
							 | 
						||
| 
								 | 
							
																var result = api.parseJSON(evt.data);
							 | 
						||
| 
								 | 
							
																if( result.id == uid ){
							 | 
						||
| 
								 | 
							
																	complete(result.status, result.statusText, result.response);
							 | 
						||
| 
								 | 
							
																}
							 | 
						||
| 
								 | 
							
															} catch( err ){
							 | 
						||
| 
								 | 
							
																complete(0, err.message);
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													// jsonp-callack
							 | 
						||
| 
								 | 
							
													complete = window[uid] = function (status, statusText, response){
							 | 
						||
| 
								 | 
							
														_this.readyState	= 4;
							 | 
						||
| 
								 | 
							
														_this.responseText	= response;
							 | 
						||
| 
								 | 
							
														_this.end(status, statusText);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														api.event.off(window, 'message', onPostMessage);
							 | 
						||
| 
								 | 
							
														window[uid] = xhr = transport = window[onloadFuncName] = null;
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												_this.xhr.abort = function (){
							 | 
						||
| 
								 | 
							
													try {
							 | 
						||
| 
								 | 
							
														if( transport.stop ){ transport.stop(); }
							 | 
						||
| 
								 | 
							
														else if( transport.contentWindow.stop ){ transport.contentWindow.stop(); }
							 | 
						||
| 
								 | 
							
														else { transport.contentWindow.document.execCommand('Stop'); }
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													catch (er) {}
							 | 
						||
| 
								 | 
							
													complete(0, "abort");
							 | 
						||
| 
								 | 
							
												};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												api.event.on(window, 'message', onPostMessage);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												window[onloadFuncName] = function (){
							 | 
						||
| 
								 | 
							
													try {
							 | 
						||
| 
								 | 
							
														var
							 | 
						||
| 
								 | 
							
															  win = transport.contentWindow
							 | 
						||
| 
								 | 
							
															, doc = win.document
							 | 
						||
| 
								 | 
							
															, result = win.result || api.parseJSON(doc.body.innerHTML)
							 | 
						||
| 
								 | 
							
														;
							 | 
						||
| 
								 | 
							
														complete(result.status, result.statusText, result.response);
							 | 
						||
| 
								 | 
							
													} catch (e){
							 | 
						||
| 
								 | 
							
														api.log('[transport.onload]', e);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												xhr = document.createElement('div');
							 | 
						||
| 
								 | 
							
												xhr.innerHTML = '<form target="'+ uid +'" action="'+ url +'" method="POST" enctype="multipart/form-data" style="position: absolute; top: -1000px; overflow: hidden; width: 1px; height: 1px;">'
							 | 
						||
| 
								 | 
							
															+ '<iframe name="'+ uid +'" src="javascript:false;" onload="' + onloadFuncName + '()"></iframe>'
							 | 
						||
| 
								 | 
							
															+ (jsonp && (options.url.indexOf('=?') < 0) ? '<input value="'+ uid +'" name="'+jsonp+'" type="hidden"/>' : '')
							 | 
						||
| 
								 | 
							
															+ '</form>'
							 | 
						||
| 
								 | 
							
												;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// get form-data & transport
							 | 
						||
| 
								 | 
							
												var
							 | 
						||
| 
								 | 
							
													  form = xhr.getElementsByTagName('form')[0]
							 | 
						||
| 
								 | 
							
													, transport = xhr.getElementsByTagName('iframe')[0]
							 | 
						||
| 
								 | 
							
												;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												form.appendChild(data);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												api.log(form.parentNode.innerHTML);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// append to DOM
							 | 
						||
| 
								 | 
							
												document.body.appendChild(xhr);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// keep a reference to node-transport
							 | 
						||
| 
								 | 
							
												_this.xhr.node = xhr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// send
							 | 
						||
| 
								 | 
							
												_this.readyState = 2; // loaded
							 | 
						||
| 
								 | 
							
												form.submit();
							 | 
						||
| 
								 | 
							
												form = null;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else {
							 | 
						||
| 
								 | 
							
												// Clean url
							 | 
						||
| 
								 | 
							
												url = url.replace(/([a-z]+)=(\?)&?/i, '');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// html5
							 | 
						||
| 
								 | 
							
												if (this.xhr && this.xhr.aborted) {
							 | 
						||
| 
								 | 
							
													api.log("Error: already aborted");
							 | 
						||
| 
								 | 
							
													return;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												xhr = _this.xhr = api.getXHR();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if (data.params) {
							 | 
						||
| 
								 | 
							
													url += (url.indexOf('?') < 0 ? "?" : "&") + data.params.join("&");
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												xhr.open('POST', url, true);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( api.withCredentials ){
							 | 
						||
| 
								 | 
							
													xhr.withCredentials = "true";
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( !options.headers || !options.headers['X-Requested-With'] ){
							 | 
						||
| 
								 | 
							
													xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												api.each(options.headers, function (val, key){
							 | 
						||
| 
								 | 
							
													xhr.setRequestHeader(key, val);
							 | 
						||
| 
								 | 
							
												});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if ( options._chunked ) {
							 | 
						||
| 
								 | 
							
													// chunked upload
							 | 
						||
| 
								 | 
							
													if( xhr.upload ){
							 | 
						||
| 
								 | 
							
														xhr.upload.addEventListener('progress', api.throttle(function (/**Event*/evt){
							 | 
						||
| 
								 | 
							
															if (!data.retry) {
							 | 
						||
| 
								 | 
							
																// show progress only for correct chunk uploads
							 | 
						||
| 
								 | 
							
																options.progress({
							 | 
						||
| 
								 | 
							
																	  type:			evt.type
							 | 
						||
| 
								 | 
							
																	, total:		data.size
							 | 
						||
| 
								 | 
							
																	, loaded:		data.start + evt.loaded
							 | 
						||
| 
								 | 
							
																	, totalSize:	data.size
							 | 
						||
| 
								 | 
							
																}, _this, options);
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
														}, 100), false);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													xhr.onreadystatechange = function (){
							 | 
						||
| 
								 | 
							
														var lkb = parseInt(xhr.getResponseHeader('X-Last-Known-Byte'), 10);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														_this.status     = xhr.status;
							 | 
						||
| 
								 | 
							
														_this.statusText = xhr.statusText;
							 | 
						||
| 
								 | 
							
														_this.readyState = xhr.readyState;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														if( xhr.readyState == 4 ){
							 | 
						||
| 
								 | 
							
															for( var k in _xhrResponsePostfix ){
							 | 
						||
| 
								 | 
							
																_this['response'+k]  = xhr['response'+k];
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
															xhr.onreadystatechange = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															if (!xhr.status || xhr.status - 201 > 0) {
							 | 
						||
| 
								 | 
							
																api.log("Error: " + xhr.status);
							 | 
						||
| 
								 | 
							
																// some kind of error
							 | 
						||
| 
								 | 
							
																// 0 - connection fail or timeout, if xhr.aborted is true, then it's not recoverable user action
							 | 
						||
| 
								 | 
							
																// up - server error
							 | 
						||
| 
								 | 
							
																if (((!xhr.status && !xhr.aborted) || 500 == xhr.status || 416 == xhr.status) && ++data.retry <= options.chunkUploadRetry) {
							 | 
						||
| 
								 | 
							
																	// let's try again the same chunk
							 | 
						||
| 
								 | 
							
																	// only applicable for recoverable error codes 500 && 416
							 | 
						||
| 
								 | 
							
																	var delay = xhr.status ? 0 : api.chunkNetworkDownRetryTimeout;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																	// inform about recoverable problems
							 | 
						||
| 
								 | 
							
																	options.pause(data.file, options);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																	// smart restart if server reports about the last known byte
							 | 
						||
| 
								 | 
							
																	api.log("X-Last-Known-Byte: " + lkb);
							 | 
						||
| 
								 | 
							
																	if (lkb) {
							 | 
						||
| 
								 | 
							
																		data.end = lkb;
							 | 
						||
| 
								 | 
							
																	} else {
							 | 
						||
| 
								 | 
							
																		data.end = data.start - 1;
							 | 
						||
| 
								 | 
							
																		if (416 == xhr.status) {
							 | 
						||
| 
								 | 
							
																			data.end = data.end - options.chunkSize;
							 | 
						||
| 
								 | 
							
																		}
							 | 
						||
| 
								 | 
							
																	}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																	setTimeout(function () {
							 | 
						||
| 
								 | 
							
																		_this._send(options, data);
							 | 
						||
| 
								 | 
							
																	}, delay);
							 | 
						||
| 
								 | 
							
																} else {
							 | 
						||
| 
								 | 
							
																	// no mo retries
							 | 
						||
| 
								 | 
							
																	_this.end(xhr.status);
							 | 
						||
| 
								 | 
							
																}
							 | 
						||
| 
								 | 
							
															} else {
							 | 
						||
| 
								 | 
							
																// success
							 | 
						||
| 
								 | 
							
																data.retry = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																if (data.end == data.size - 1) {
							 | 
						||
| 
								 | 
							
																	// finished
							 | 
						||
| 
								 | 
							
																	_this.end(xhr.status);
							 | 
						||
| 
								 | 
							
																} else {
							 | 
						||
| 
								 | 
							
																	// next chunk
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																	// shift position if server reports about the last known byte
							 | 
						||
| 
								 | 
							
																	api.log("X-Last-Known-Byte: " + lkb);
							 | 
						||
| 
								 | 
							
																	if (lkb) {
							 | 
						||
| 
								 | 
							
																		data.end = lkb;
							 | 
						||
| 
								 | 
							
																	}
							 | 
						||
| 
								 | 
							
																	data.file.FileAPIReadPosition = data.end;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																	setTimeout(function () {
							 | 
						||
| 
								 | 
							
																		_this._send(options, data);
							 | 
						||
| 
								 | 
							
																	}, 0);
							 | 
						||
| 
								 | 
							
																}
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															xhr = null;
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													data.start = data.end + 1;
							 | 
						||
| 
								 | 
							
													data.end = Math.max(Math.min(data.start + options.chunkSize, data.size) - 1, data.start);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													// Retrieve a slice of file
							 | 
						||
| 
								 | 
							
													var
							 | 
						||
| 
								 | 
							
														  file = data.file
							 | 
						||
| 
								 | 
							
														, slice = (file.slice || file.mozSlice || file.webkitSlice).call(file, data.start, data.end + 1)
							 | 
						||
| 
								 | 
							
													;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													if( data.size && !slice.size ){
							 | 
						||
| 
								 | 
							
														setTimeout(function (){
							 | 
						||
| 
								 | 
							
															_this.end(-1);
							 | 
						||
| 
								 | 
							
														});
							 | 
						||
| 
								 | 
							
													} else {
							 | 
						||
| 
								 | 
							
														xhr.setRequestHeader("Content-Range", "bytes " + data.start + "-" + data.end + "/" + data.size);
							 | 
						||
| 
								 | 
							
														xhr.setRequestHeader("Content-Disposition", 'attachment; filename=' + encodeURIComponent(data.name));
							 | 
						||
| 
								 | 
							
														xhr.setRequestHeader("Content-Type", data.type || "application/octet-stream");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														xhr.send(slice);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													file = slice = null;
							 | 
						||
| 
								 | 
							
												} else {
							 | 
						||
| 
								 | 
							
													// single piece upload
							 | 
						||
| 
								 | 
							
													if( xhr.upload ){
							 | 
						||
| 
								 | 
							
														// https://github.com/blueimp/jQuery-File-Upload/wiki/Fixing-Safari-hanging-on-very-high-speed-connections-%281Gbps%29
							 | 
						||
| 
								 | 
							
														xhr.upload.addEventListener('progress', api.throttle(function (/**Event*/evt){
							 | 
						||
| 
								 | 
							
															options.progress(evt, _this, options);
							 | 
						||
| 
								 | 
							
														}, 100), false);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													xhr.onreadystatechange = function (){
							 | 
						||
| 
								 | 
							
														_this.status     = xhr.status;
							 | 
						||
| 
								 | 
							
														_this.statusText = xhr.statusText;
							 | 
						||
| 
								 | 
							
														_this.readyState = xhr.readyState;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														if( xhr.readyState == 4 ){
							 | 
						||
| 
								 | 
							
															for( var k in _xhrResponsePostfix ){
							 | 
						||
| 
								 | 
							
																_this['response'+k]  = xhr['response'+k];
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
															xhr.onreadystatechange = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															if (!xhr.status || xhr.status > 201) {
							 | 
						||
| 
								 | 
							
																api.log("Error: " + xhr.status);
							 | 
						||
| 
								 | 
							
																if (((!xhr.status && !xhr.aborted) || 500 == xhr.status) && (options.retry || 0) < options.uploadRetry) {
							 | 
						||
| 
								 | 
							
																	options.retry = (options.retry || 0) + 1;
							 | 
						||
| 
								 | 
							
																	var delay = api.networkDownRetryTimeout;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																	// inform about recoverable problems
							 | 
						||
| 
								 | 
							
																	options.pause(options.file, options);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																	setTimeout(function () {
							 | 
						||
| 
								 | 
							
																		_this._send(options, data);
							 | 
						||
| 
								 | 
							
																	}, delay);
							 | 
						||
| 
								 | 
							
																} else {
							 | 
						||
| 
								 | 
							
																	//success
							 | 
						||
| 
								 | 
							
																	_this.end(xhr.status);
							 | 
						||
| 
								 | 
							
																}
							 | 
						||
| 
								 | 
							
															} else {
							 | 
						||
| 
								 | 
							
																//success
							 | 
						||
| 
								 | 
							
																_this.end(xhr.status);
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															xhr = null;
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													if( api.isArray(data) ){
							 | 
						||
| 
								 | 
							
														// multipart
							 | 
						||
| 
								 | 
							
														xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=_'+api.expando);
							 | 
						||
| 
								 | 
							
														var rawData = data.join('') +'--_'+ api.expando +'--';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														/** @namespace  xhr.sendAsBinary  https://developer.mozilla.org/ru/XMLHttpRequest#Sending_binary_content */
							 | 
						||
| 
								 | 
							
														if( xhr.sendAsBinary ){
							 | 
						||
| 
								 | 
							
															xhr.sendAsBinary(rawData);
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
														else {
							 | 
						||
| 
								 | 
							
															var bytes = Array.prototype.map.call(rawData, function(c){ return c.charCodeAt(0) & 0xff; });
							 | 
						||
| 
								 | 
							
															xhr.send(new Uint8Array(bytes).buffer);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													} else {
							 | 
						||
| 
								 | 
							
														// FormData
							 | 
						||
| 
								 | 
							
														xhr.send(data);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// @export
							 | 
						||
| 
								 | 
							
									api.XHR = XHR;
							 | 
						||
| 
								 | 
							
								})(window, FileAPI);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @class	FileAPI.Camera
							 | 
						||
| 
								 | 
							
								 * @author	RubaXa	<trash@rubaxa.org>
							 | 
						||
| 
								 | 
							
								 * @support	Chrome 21+, FF 18+, Opera 12+
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*global window, FileAPI, jQuery */
							 | 
						||
| 
								 | 
							
								/** @namespace LocalMediaStream -- https://developer.mozilla.org/en-US/docs/WebRTC/MediaStream_API#LocalMediaStream */
							 | 
						||
| 
								 | 
							
								(function (window, api){
							 | 
						||
| 
								 | 
							
									"use strict";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									var
							 | 
						||
| 
								 | 
							
										URL = window.URL || window.webkitURL,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										document = window.document,
							 | 
						||
| 
								 | 
							
										navigator = window.navigator,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										getMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										html5 = !!getMedia
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Support "media"
							 | 
						||
| 
								 | 
							
									api.support.media = html5;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									var Camera = function (video){
							 | 
						||
| 
								 | 
							
										this.video = video;
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									Camera.prototype = {
							 | 
						||
| 
								 | 
							
										isActive: function (){
							 | 
						||
| 
								 | 
							
											return	!!this._active;
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/**
							 | 
						||
| 
								 | 
							
										 * Start camera streaming
							 | 
						||
| 
								 | 
							
										 * @param	{Function}	callback
							 | 
						||
| 
								 | 
							
										 */
							 | 
						||
| 
								 | 
							
										start: function (callback){
							 | 
						||
| 
								 | 
							
											var
							 | 
						||
| 
								 | 
							
												  _this = this
							 | 
						||
| 
								 | 
							
												, video = _this.video
							 | 
						||
| 
								 | 
							
												, _successId
							 | 
						||
| 
								 | 
							
												, _failId
							 | 
						||
| 
								 | 
							
												, _complete = function (err){
							 | 
						||
| 
								 | 
							
													_this._active = !err;
							 | 
						||
| 
								 | 
							
													clearTimeout(_failId);
							 | 
						||
| 
								 | 
							
													clearTimeout(_successId);
							 | 
						||
| 
								 | 
							
								//					api.event.off(video, 'loadedmetadata', _complete);
							 | 
						||
| 
								 | 
							
													callback && callback(err, _this);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											getMedia.call(navigator, { video: true }, function (stream/**LocalMediaStream*/){
							 | 
						||
| 
								 | 
							
												// Success
							 | 
						||
| 
								 | 
							
												_this.stream = stream;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//				api.event.on(video, 'loadedmetadata', function (){
							 | 
						||
| 
								 | 
							
								//					_complete(null);
							 | 
						||
| 
								 | 
							
								//				});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// Set camera stream
							 | 
						||
| 
								 | 
							
												video.src = URL.createObjectURL(stream);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// Note: onloadedmetadata doesn't fire in Chrome when using it with getUserMedia.
							 | 
						||
| 
								 | 
							
												// See crbug.com/110938.
							 | 
						||
| 
								 | 
							
												_successId = setInterval(function (){
							 | 
						||
| 
								 | 
							
													if( _detectVideoSignal(video) ){
							 | 
						||
| 
								 | 
							
														_complete(null);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}, 1000);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												_failId = setTimeout(function (){
							 | 
						||
| 
								 | 
							
													_complete('timeout');
							 | 
						||
| 
								 | 
							
												}, 5000);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// Go-go-go!
							 | 
						||
| 
								 | 
							
												video.play();
							 | 
						||
| 
								 | 
							
											}, _complete/*error*/);
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/**
							 | 
						||
| 
								 | 
							
										 * Stop camera streaming
							 | 
						||
| 
								 | 
							
										 */
							 | 
						||
| 
								 | 
							
										stop: function (){
							 | 
						||
| 
								 | 
							
											try {
							 | 
						||
| 
								 | 
							
												this._active = false;
							 | 
						||
| 
								 | 
							
												this.video.pause();
							 | 
						||
| 
								 | 
							
												this.stream.stop();
							 | 
						||
| 
								 | 
							
											} catch( err ){ }
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/**
							 | 
						||
| 
								 | 
							
										 * Create screenshot
							 | 
						||
| 
								 | 
							
										 * @return {FileAPI.Camera.Shot}
							 | 
						||
| 
								 | 
							
										 */
							 | 
						||
| 
								 | 
							
										shot: function (){
							 | 
						||
| 
								 | 
							
											return	new Shot(this.video);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Get camera element from container
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @static
							 | 
						||
| 
								 | 
							
									 * @param	{HTMLElement}	el
							 | 
						||
| 
								 | 
							
									 * @return	{Camera}
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									Camera.get = function (el){
							 | 
						||
| 
								 | 
							
										return	new Camera(el.firstChild);
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Publish camera element into container
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @static
							 | 
						||
| 
								 | 
							
									 * @param	{HTMLElement}	el
							 | 
						||
| 
								 | 
							
									 * @param	{Object}		options
							 | 
						||
| 
								 | 
							
									 * @param	{Function}		[callback]
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									Camera.publish = function (el, options, callback){
							 | 
						||
| 
								 | 
							
										if( typeof options == 'function' ){
							 | 
						||
| 
								 | 
							
											callback = options;
							 | 
						||
| 
								 | 
							
											options = {};
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Dimensions of "camera"
							 | 
						||
| 
								 | 
							
										options = api.extend({}, {
							 | 
						||
| 
								 | 
							
											  width:	'100%'
							 | 
						||
| 
								 | 
							
											, height:	'100%'
							 | 
						||
| 
								 | 
							
											, start:	true
							 | 
						||
| 
								 | 
							
										}, options);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if( el.jquery ){
							 | 
						||
| 
								 | 
							
											// Extract first element, from jQuery collection
							 | 
						||
| 
								 | 
							
											el = el[0];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										var doneFn = function (err){
							 | 
						||
| 
								 | 
							
											if( err ){
							 | 
						||
| 
								 | 
							
												callback(err);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else {
							 | 
						||
| 
								 | 
							
												// Get camera
							 | 
						||
| 
								 | 
							
												var cam = Camera.get(el);
							 | 
						||
| 
								 | 
							
												if( options.start ){
							 | 
						||
| 
								 | 
							
													cam.start(callback);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else {
							 | 
						||
| 
								 | 
							
													callback(null, cam);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										el.style.width	= _px(options.width);
							 | 
						||
| 
								 | 
							
										el.style.height	= _px(options.height);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if( api.html5 && html5 ){
							 | 
						||
| 
								 | 
							
											// Create video element
							 | 
						||
| 
								 | 
							
											var video = document.createElement('video');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Set dimensions
							 | 
						||
| 
								 | 
							
											video.style.width	= _px(options.width);
							 | 
						||
| 
								 | 
							
											video.style.height	= _px(options.height);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Clean container
							 | 
						||
| 
								 | 
							
											if( window.jQuery ){
							 | 
						||
| 
								 | 
							
												jQuery(el).empty();
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
												el.innerHTML = '';
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Add "camera" to container
							 | 
						||
| 
								 | 
							
											el.appendChild(video);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// end
							 | 
						||
| 
								 | 
							
											doneFn();
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else {
							 | 
						||
| 
								 | 
							
											Camera.fallback(el, options, doneFn);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									Camera.fallback = function (el, options, callback){
							 | 
						||
| 
								 | 
							
										callback('not_support_camera');
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * @class	FileAPI.Camera.Shot
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									var Shot = function (video){
							 | 
						||
| 
								 | 
							
										var canvas	= video.nodeName ? api.Image.toCanvas(video) : video;
							 | 
						||
| 
								 | 
							
										var shot	= api.Image(canvas);
							 | 
						||
| 
								 | 
							
										shot.type	= 'image/png';
							 | 
						||
| 
								 | 
							
										shot.width	= canvas.width;
							 | 
						||
| 
								 | 
							
										shot.height	= canvas.height;
							 | 
						||
| 
								 | 
							
										shot.size	= canvas.width * canvas.height * 4;
							 | 
						||
| 
								 | 
							
										return	shot;
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Add "px" postfix, if value is a number
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @private
							 | 
						||
| 
								 | 
							
									 * @param	{*}  val
							 | 
						||
| 
								 | 
							
									 * @return	{String}
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									function _px(val){
							 | 
						||
| 
								 | 
							
										return	val >= 0 ? val + 'px' : val;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * @private
							 | 
						||
| 
								 | 
							
									 * @param	{HTMLVideoElement} video
							 | 
						||
| 
								 | 
							
									 * @return	{Boolean}
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									function _detectVideoSignal(video){
							 | 
						||
| 
								 | 
							
										var canvas = document.createElement('canvas'), ctx, res = false;
							 | 
						||
| 
								 | 
							
										try {
							 | 
						||
| 
								 | 
							
											ctx = canvas.getContext('2d');
							 | 
						||
| 
								 | 
							
											ctx.drawImage(video, 0, 0, 1, 1);
							 | 
						||
| 
								 | 
							
											res = ctx.getImageData(0, 0, 1, 1).data[4] != 255;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										catch( e ){}
							 | 
						||
| 
								 | 
							
										return	res;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// @export
							 | 
						||
| 
								 | 
							
									Camera.Shot	= Shot;
							 | 
						||
| 
								 | 
							
									api.Camera	= Camera;
							 | 
						||
| 
								 | 
							
								})(window, FileAPI);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * FileAPI fallback to Flash
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @flash-developer  "Vladimir Demidov" <v.demidov@corp.mail.ru>
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*global window, ActiveXObject, FileAPI */
							 | 
						||
| 
								 | 
							
								(function (window, jQuery, api) {
							 | 
						||
| 
								 | 
							
									"use strict";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									var
							 | 
						||
| 
								 | 
							
										  document = window.document
							 | 
						||
| 
								 | 
							
										, location = window.location
							 | 
						||
| 
								 | 
							
										, navigator = window.navigator
							 | 
						||
| 
								 | 
							
										, _each = api.each
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									api.support.flash = (function (){
							 | 
						||
| 
								 | 
							
										var mime = navigator.mimeTypes, has = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if( navigator.plugins && typeof navigator.plugins['Shockwave Flash'] == 'object' ){
							 | 
						||
| 
								 | 
							
											has	= navigator.plugins['Shockwave Flash'].description && !(mime && mime['application/x-shockwave-flash'] && !mime['application/x-shockwave-flash'].enabledPlugin);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else {
							 | 
						||
| 
								 | 
							
											try {
							 | 
						||
| 
								 | 
							
												has	= !!(window.ActiveXObject && new ActiveXObject('ShockwaveFlash.ShockwaveFlash'));
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											catch(er){
							 | 
						||
| 
								 | 
							
												api.log('Flash -- does not supported.');
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if( has && /^file:/i.test(location) ){
							 | 
						||
| 
								 | 
							
											api.log('[warn] Flash does not work on `file:` protocol.');
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return	has;
							 | 
						||
| 
								 | 
							
									})();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									   api.support.flash
							 | 
						||
| 
								 | 
							
									&& (0
							 | 
						||
| 
								 | 
							
										|| !api.html5 || !api.support.html5
							 | 
						||
| 
								 | 
							
										|| (api.cors && !api.support.cors)
							 | 
						||
| 
								 | 
							
										|| (api.media && !api.support.media)
							 | 
						||
| 
								 | 
							
									)
							 | 
						||
| 
								 | 
							
									&& (function (){
							 | 
						||
| 
								 | 
							
										var
							 | 
						||
| 
								 | 
							
											  _attr  = api.uid()
							 | 
						||
| 
								 | 
							
											, _retry = 0
							 | 
						||
| 
								 | 
							
											, _files = {}
							 | 
						||
| 
								 | 
							
											, _rhttp = /^https?:/i
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											, flash = {
							 | 
						||
| 
								 | 
							
												_fn: {},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												/**
							 | 
						||
| 
								 | 
							
												 * Initialization & preload flash object
							 | 
						||
| 
								 | 
							
												 */
							 | 
						||
| 
								 | 
							
												init: function (){
							 | 
						||
| 
								 | 
							
													var child = document.body && document.body.firstChild;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													if( child ){
							 | 
						||
| 
								 | 
							
														do {
							 | 
						||
| 
								 | 
							
															if( child.nodeType == 1 ){
							 | 
						||
| 
								 | 
							
																api.log('FlashAPI.state: awaiting');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																var dummy = document.createElement('div');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																dummy.id = '_' + _attr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																_css(dummy, {
							 | 
						||
| 
								 | 
							
																	  top: 1
							 | 
						||
| 
								 | 
							
																	, right: 1
							 | 
						||
| 
								 | 
							
																	, width: 5
							 | 
						||
| 
								 | 
							
																	, height: 5
							 | 
						||
| 
								 | 
							
																	, position: 'absolute'
							 | 
						||
| 
								 | 
							
																	, zIndex: 1e6+'' // set max zIndex
							 | 
						||
| 
								 | 
							
																});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																child.parentNode.insertBefore(dummy, child);
							 | 
						||
| 
								 | 
							
																flash.publish(dummy, _attr);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																return;
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
														while( child = child.nextSibling );
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													if( _retry < 10 ){
							 | 
						||
| 
								 | 
							
														setTimeout(flash.init, ++_retry*50);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												/**
							 | 
						||
| 
								 | 
							
												 * Publish flash-object
							 | 
						||
| 
								 | 
							
												 *
							 | 
						||
| 
								 | 
							
												 * @param {HTMLElement} el
							 | 
						||
| 
								 | 
							
												 * @param {String} id
							 | 
						||
| 
								 | 
							
												 * @param {Object} [opts]
							 | 
						||
| 
								 | 
							
												 */
							 | 
						||
| 
								 | 
							
												publish: function (el, id, opts){
							 | 
						||
| 
								 | 
							
													opts = opts || {};
							 | 
						||
| 
								 | 
							
													el.innerHTML = _makeFlashHTML({
							 | 
						||
| 
								 | 
							
														  id: id
							 | 
						||
| 
								 | 
							
														, src: _getUrl(api.flashUrl, 'r=' + api.version)
							 | 
						||
| 
								 | 
							
								//						, src: _getUrl('http://v.demidov.boom.corp.mail.ru/uploaderfileapi/FlashFileAPI.swf?1')
							 | 
						||
| 
								 | 
							
														, wmode: opts.camera ? '' : 'transparent'
							 | 
						||
| 
								 | 
							
														, flashvars: 'callback=' + (opts.onEvent || 'FileAPI.Flash.onEvent')
							 | 
						||
| 
								 | 
							
															+ '&flashId='+ id
							 | 
						||
| 
								 | 
							
															+ '&storeKey='+ navigator.userAgent.match(/\d/ig).join('') +'_'+ api.version
							 | 
						||
| 
								 | 
							
															+ (flash.isReady || (api.pingUrl ? '&ping='+api.pingUrl : ''))
							 | 
						||
| 
								 | 
							
															+ '&timeout='+api.flashAbortTimeout
							 | 
						||
| 
								 | 
							
															+ (opts.camera ? '&useCamera=' + _getUrl(api.flashWebcamUrl) : '')
							 | 
						||
| 
								 | 
							
															+ '&debug='+(api.debug?"1":"")
							 | 
						||
| 
								 | 
							
													}, opts);
							 | 
						||
| 
								 | 
							
												},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												ready: function (){
							 | 
						||
| 
								 | 
							
													api.log('FlashAPI.state: ready');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													flash.ready = api.F;
							 | 
						||
| 
								 | 
							
													flash.isReady = true;
							 | 
						||
| 
								 | 
							
													flash.patch();
							 | 
						||
| 
								 | 
							
													flash.patchCamera && flash.patchCamera();
							 | 
						||
| 
								 | 
							
													api.event.on(document, 'mouseover', flash.mouseover);
							 | 
						||
| 
								 | 
							
													api.event.on(document, 'click', function (evt){
							 | 
						||
| 
								 | 
							
														if( flash.mouseover(evt) ){
							 | 
						||
| 
								 | 
							
															evt.preventDefault
							 | 
						||
| 
								 | 
							
																? evt.preventDefault()
							 | 
						||
| 
								 | 
							
																: (evt.returnValue = true)
							 | 
						||
| 
								 | 
							
															;
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													});
							 | 
						||
| 
								 | 
							
												},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												getEl: function (){
							 | 
						||
| 
								 | 
							
													return	document.getElementById('_'+_attr);
							 | 
						||
| 
								 | 
							
												},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												getWrapper: function (node){
							 | 
						||
| 
								 | 
							
													do {
							 | 
						||
| 
								 | 
							
														if( /js-fileapi-wrapper/.test(node.className) ){
							 | 
						||
| 
								 | 
							
															return	node;
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													while( (node = node.parentNode) && (node !== document.body) );
							 | 
						||
| 
								 | 
							
												},
							 | 
						||
| 
								 | 
							
												
							 | 
						||
| 
								 | 
							
												disableMouseover: false,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												mouseover: function (evt){
							 | 
						||
| 
								 | 
							
													if (!flash.disableMouseover) {
							 | 
						||
| 
								 | 
							
														var target = api.event.fix(evt).target;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
														if( /input/i.test(target.nodeName) && target.type == 'file' && !target.disabled ){
							 | 
						||
| 
								 | 
							
															var
							 | 
						||
| 
								 | 
							
																  state = target.getAttribute(_attr)
							 | 
						||
| 
								 | 
							
																, wrapper = flash.getWrapper(target)
							 | 
						||
| 
								 | 
							
															;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
															if( api.multiFlash ){
							 | 
						||
| 
								 | 
							
																// check state:
							 | 
						||
| 
								 | 
							
																//   i — published
							 | 
						||
| 
								 | 
							
																//   i — initialization
							 | 
						||
| 
								 | 
							
																//   r — ready
							 | 
						||
| 
								 | 
							
																if( state == 'i' || state == 'r' ){
							 | 
						||
| 
								 | 
							
																	// publish fail
							 | 
						||
| 
								 | 
							
																	return	false;
							 | 
						||
| 
								 | 
							
																}
							 | 
						||
| 
								 | 
							
																else if( state != 'p' ){
							 | 
						||
| 
								 | 
							
																	// set "init" state
							 | 
						||
| 
								 | 
							
																	target.setAttribute(_attr, 'i');
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
																	var dummy = document.createElement('div');
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
																	if( !wrapper ){
							 | 
						||
| 
								 | 
							
																		api.log('[err] FlashAPI.mouseover: js-fileapi-wrapper not found');
							 | 
						||
| 
								 | 
							
																		return;
							 | 
						||
| 
								 | 
							
																	}
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
																	_css(dummy, {
							 | 
						||
| 
								 | 
							
																		  top:    0
							 | 
						||
| 
								 | 
							
																		, left:   0
							 | 
						||
| 
								 | 
							
																		, width:  target.offsetWidth
							 | 
						||
| 
								 | 
							
																		, height: target.offsetHeight
							 | 
						||
| 
								 | 
							
																		, zIndex: 1e6+'' // set max zIndex
							 | 
						||
| 
								 | 
							
																		, position: 'absolute'
							 | 
						||
| 
								 | 
							
																	});
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
																	wrapper.appendChild(dummy);
							 | 
						||
| 
								 | 
							
																	flash.publish(dummy, api.uid());
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
																	// set "publish" state
							 | 
						||
| 
								 | 
							
																	target.setAttribute(_attr, 'p');
							 | 
						||
| 
								 | 
							
																}
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
																return	true;
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
															else if( wrapper ){
							 | 
						||
| 
								 | 
							
																// Use one flash element
							 | 
						||
| 
								 | 
							
																var box = _getDimensions(wrapper);
							 | 
						||
| 
								 | 
							
																_css(flash.getEl(), box);
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
																// Set current input
							 | 
						||
| 
								 | 
							
																flash.curInp = target;
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
														else if( !/object|embed/i.test(target.nodeName) ){
							 | 
						||
| 
								 | 
							
															_css(flash.getEl(), { top: 1, left: 1, width: 5, height: 5 });
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												onEvent: function (evt){
							 | 
						||
| 
								 | 
							
													var type = evt.type;
							 | 
						||
| 
								 | 
							
													
							 | 
						||
| 
								 | 
							
													if( type == 'ready' ){
							 | 
						||
| 
								 | 
							
														try {
							 | 
						||
| 
								 | 
							
															// set "ready" state
							 | 
						||
| 
								 | 
							
															flash.getInput(evt.flashId).setAttribute(_attr, 'r');
							 | 
						||
| 
								 | 
							
														} catch (e){
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														flash.ready();
							 | 
						||
| 
								 | 
							
														setTimeout(function (){ flash.mouseenter(evt); }, 50);
							 | 
						||
| 
								 | 
							
														return	true;
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													else if( type === 'ping' ){
							 | 
						||
| 
								 | 
							
														api.log('(flash -> js).ping:', [evt.status, evt.savedStatus], evt.error);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													else if( type === 'log' ){
							 | 
						||
| 
								 | 
							
														api.log('(flash -> js).log:', evt.target);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													else if( type in flash ){
							 | 
						||
| 
								 | 
							
														setTimeout(function (){
							 | 
						||
| 
								 | 
							
															api.log('FlashAPI.event.'+evt.type+':', evt);
							 | 
						||
| 
								 | 
							
															flash[type](evt);
							 | 
						||
| 
								 | 
							
														}, 1);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												},
							 | 
						||
| 
								 | 
							
												mouseDown: function(evt) {
							 | 
						||
| 
								 | 
							
													flash.disableMouseover = true;
							 | 
						||
| 
								 | 
							
												},
							 | 
						||
| 
								 | 
							
												cancel: function(evt) {
							 | 
						||
| 
								 | 
							
													flash.disableMouseover = false;
							 | 
						||
| 
								 | 
							
												},
							 | 
						||
| 
								 | 
							
												mouseenter: function (evt){
							 | 
						||
| 
								 | 
							
													var node = flash.getInput(evt.flashId);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													if( node ){
							 | 
						||
| 
								 | 
							
														// Set multiple mode
							 | 
						||
| 
								 | 
							
														flash.cmd(evt, 'multiple', node.getAttribute('multiple') != null);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														// Set files filter
							 | 
						||
| 
								 | 
							
														var accept = [], exts = {};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														_each((node.getAttribute('accept') || '').split(/,\s*/), function (mime){
							 | 
						||
| 
								 | 
							
															api.accept[mime] && _each(api.accept[mime].split(' '), function (ext){
							 | 
						||
| 
								 | 
							
																exts[ext] = 1;
							 | 
						||
| 
								 | 
							
															});
							 | 
						||
| 
								 | 
							
														});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														_each(exts, function (i, ext){
							 | 
						||
| 
								 | 
							
															accept.push( ext );
							 | 
						||
| 
								 | 
							
														});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														flash.cmd(evt, 'accept', accept.length ? accept.join(',')+','+accept.join(',').toUpperCase() : '*');
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												get: function (id){
							 | 
						||
| 
								 | 
							
													return	document[id] || window[id] || document.embeds[id];
							 | 
						||
| 
								 | 
							
												},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												getInput: function (id){
							 | 
						||
| 
								 | 
							
													if( api.multiFlash ){
							 | 
						||
| 
								 | 
							
														try {
							 | 
						||
| 
								 | 
							
															var node = flash.getWrapper(flash.get(id));
							 | 
						||
| 
								 | 
							
															if( node ){
							 | 
						||
| 
								 | 
							
																return node.getElementsByTagName('input')[0];
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
														} catch (e){
							 | 
						||
| 
								 | 
							
															api.log('[err] Can not find "input" by flashId:', id, e);
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													} else {
							 | 
						||
| 
								 | 
							
														return	flash.curInp;
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												select: function (evt){
							 | 
						||
| 
								 | 
							
													try {
							 | 
						||
| 
								 | 
							
														var
							 | 
						||
| 
								 | 
							
															  inp = flash.getInput(evt.flashId)
							 | 
						||
| 
								 | 
							
															, uid = api.uid(inp)
							 | 
						||
| 
								 | 
							
															, files = evt.target.files
							 | 
						||
| 
								 | 
							
															, event
							 | 
						||
| 
								 | 
							
														;
							 | 
						||
| 
								 | 
							
														_each(files, function (file){
							 | 
						||
| 
								 | 
							
															api.checkFileObj(file);
							 | 
						||
| 
								 | 
							
														});
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
														_files[uid] = files;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
														if( document.createEvent ){
							 | 
						||
| 
								 | 
							
															event = document.createEvent('Event');
							 | 
						||
| 
								 | 
							
															event.files = files;
							 | 
						||
| 
								 | 
							
															event.initEvent('change', true, true);
							 | 
						||
| 
								 | 
							
															inp.dispatchEvent(event);
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
														else if( jQuery ){
							 | 
						||
| 
								 | 
							
															jQuery(inp).trigger({ type: 'change', files: files });
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
														else {
							 | 
						||
| 
								 | 
							
															event = document.createEventObject();
							 | 
						||
| 
								 | 
							
															event.files = files;
							 | 
						||
| 
								 | 
							
															inp.fireEvent('onchange', event);
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													} finally {
							 | 
						||
| 
								 | 
							
														flash.disableMouseover = false;
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												cmd: function (id, name, data, last){
							 | 
						||
| 
								 | 
							
													try {
							 | 
						||
| 
								 | 
							
														api.log('(js -> flash).'+name+':', data);
							 | 
						||
| 
								 | 
							
														return flash.get(id.flashId || id).cmd(name, data);
							 | 
						||
| 
								 | 
							
													} catch (e){
							 | 
						||
| 
								 | 
							
														api.log('(js -> flash).onError:', e);
							 | 
						||
| 
								 | 
							
														if( !last ){
							 | 
						||
| 
								 | 
							
															// try again
							 | 
						||
| 
								 | 
							
															setTimeout(function (){ flash.cmd(id, name, data, true); }, 50);
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												patch: function (){
							 | 
						||
| 
								 | 
							
													api.flashEngine = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													// FileAPI
							 | 
						||
| 
								 | 
							
													_inherit(api, {
							 | 
						||
| 
								 | 
							
														getFiles: function (input, filter, callback){
							 | 
						||
| 
								 | 
							
															if( callback ){
							 | 
						||
| 
								 | 
							
																api.filterFiles(api.getFiles(input), filter, callback);
							 | 
						||
| 
								 | 
							
																return null;
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															var files = api.isArray(input) ? input : _files[api.uid(input.target || input.srcElement || input)];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															if( !files ){
							 | 
						||
| 
								 | 
							
																// Файлов нету, вызываем родительский метод
							 | 
						||
| 
								 | 
							
																return	this.parent.apply(this, arguments);
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															if( filter ){
							 | 
						||
| 
								 | 
							
																filter	= api.getFilesFilter(filter);
							 | 
						||
| 
								 | 
							
																files	= api.filter(files, function (file){ return filter.test(file.name); });
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															return	files;
							 | 
						||
| 
								 | 
							
														},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														getInfo: function (file, fn){
							 | 
						||
| 
								 | 
							
															if( _isHtmlFile(file) ){
							 | 
						||
| 
								 | 
							
																this.parent.apply(this, arguments);
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
															else if( file.isShot ){
							 | 
						||
| 
								 | 
							
																fn(null, file.info = {
							 | 
						||
| 
								 | 
							
																	width: file.width,
							 | 
						||
| 
								 | 
							
																	height: file.height
							 | 
						||
| 
								 | 
							
																});
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
															else {
							 | 
						||
| 
								 | 
							
																if( !file.__info ){
							 | 
						||
| 
								 | 
							
																	var defer = file.__info = api.defer();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//									flash.cmd(file, 'getFileInfo', {
							 | 
						||
| 
								 | 
							
								//										  id: file.id
							 | 
						||
| 
								 | 
							
								//										, callback: _wrap(function _(err, info){
							 | 
						||
| 
								 | 
							
								//											_unwrap(_);
							 | 
						||
| 
								 | 
							
								//											defer.resolve(err, file.info = info);
							 | 
						||
| 
								 | 
							
								//										})
							 | 
						||
| 
								 | 
							
								//									});
							 | 
						||
| 
								 | 
							
																	defer.resolve(null, file.info = null);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																file.__info.then(fn);
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													// FileAPI.Image
							 | 
						||
| 
								 | 
							
													api.support.transform = true;
							 | 
						||
| 
								 | 
							
													api.Image && _inherit(api.Image.prototype, {
							 | 
						||
| 
								 | 
							
														get: function (fn, scaleMode){
							 | 
						||
| 
								 | 
							
															this.set({ scaleMode: scaleMode || 'noScale' }); // noScale, exactFit
							 | 
						||
| 
								 | 
							
															return this.parent(fn);
							 | 
						||
| 
								 | 
							
														},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														_load: function (file, fn){
							 | 
						||
| 
								 | 
							
															api.log('FlashAPI.Image._load:', file);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															if( _isHtmlFile(file) ){
							 | 
						||
| 
								 | 
							
																this.parent.apply(this, arguments);
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
															else {
							 | 
						||
| 
								 | 
							
																var _this = this;
							 | 
						||
| 
								 | 
							
																api.getInfo(file, function (err){
							 | 
						||
| 
								 | 
							
																	fn.call(_this, err, file);
							 | 
						||
| 
								 | 
							
																});
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
														},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														_apply: function (file, fn){
							 | 
						||
| 
								 | 
							
															api.log('FlashAPI.Image._apply:', file);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															if( _isHtmlFile(file) ){
							 | 
						||
| 
								 | 
							
																this.parent.apply(this, arguments);
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
															else {
							 | 
						||
| 
								 | 
							
																var m = this.getMatrix(file.info), doneFn = fn;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																flash.cmd(file, 'imageTransform', {
							 | 
						||
| 
								 | 
							
																	  id: file.id
							 | 
						||
| 
								 | 
							
																	, matrix: m
							 | 
						||
| 
								 | 
							
																	, callback: _wrap(function _(err, base64){
							 | 
						||
| 
								 | 
							
																		api.log('FlashAPI.Image._apply.callback:', err);
							 | 
						||
| 
								 | 
							
																		_unwrap(_);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																		if( err ){
							 | 
						||
| 
								 | 
							
																			doneFn(err);
							 | 
						||
| 
								 | 
							
																		}
							 | 
						||
| 
								 | 
							
																		else if( !api.support.html5 && (!api.support.dataURI || base64.length > 3e4) ){
							 | 
						||
| 
								 | 
							
																			_makeFlashImage({
							 | 
						||
| 
								 | 
							
																				  width:	(m.deg % 180) ? m.dh : m.dw
							 | 
						||
| 
								 | 
							
																				, height:	(m.deg % 180) ? m.dw : m.dh
							 | 
						||
| 
								 | 
							
																				, scale:	m.scaleMode
							 | 
						||
| 
								 | 
							
																			}, base64, doneFn);
							 | 
						||
| 
								 | 
							
																		}
							 | 
						||
| 
								 | 
							
																		else {
							 | 
						||
| 
								 | 
							
																			if( m.filter ){
							 | 
						||
| 
								 | 
							
																				doneFn = function (err, img){
							 | 
						||
| 
								 | 
							
																					if( err ){
							 | 
						||
| 
								 | 
							
																						fn(err);
							 | 
						||
| 
								 | 
							
																					}
							 | 
						||
| 
								 | 
							
																					else {
							 | 
						||
| 
								 | 
							
																						api.Image.applyFilter(img, m.filter, function (){
							 | 
						||
| 
								 | 
							
																							fn(err, this.canvas);
							 | 
						||
| 
								 | 
							
																						});
							 | 
						||
| 
								 | 
							
																					}
							 | 
						||
| 
								 | 
							
																				};
							 | 
						||
| 
								 | 
							
																			}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																			api.newImage('data:'+ file.type +';base64,'+ base64, doneFn);
							 | 
						||
| 
								 | 
							
																		}
							 | 
						||
| 
								 | 
							
																	})
							 | 
						||
| 
								 | 
							
																});
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
														},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														toData: function (fn){
							 | 
						||
| 
								 | 
							
															var
							 | 
						||
| 
								 | 
							
																  file = this.file
							 | 
						||
| 
								 | 
							
																, info = file.info
							 | 
						||
| 
								 | 
							
																, matrix = this.getMatrix(info)
							 | 
						||
| 
								 | 
							
															;
							 | 
						||
| 
								 | 
							
															api.log('FlashAPI.Image.toData');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															if( _isHtmlFile(file) ){
							 | 
						||
| 
								 | 
							
																this.parent.apply(this, arguments);
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
															else {
							 | 
						||
| 
								 | 
							
																if( matrix.deg == 'auto' ){
							 | 
						||
| 
								 | 
							
																	matrix.deg = api.Image.exifOrientation[info && info.exif && info.exif.Orientation] || 0;
							 | 
						||
| 
								 | 
							
																}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																fn.call(this, !file.info, {
							 | 
						||
| 
								 | 
							
																	  id:		file.id
							 | 
						||
| 
								 | 
							
																	, flashId:	file.flashId
							 | 
						||
| 
								 | 
							
																	, name:		file.name
							 | 
						||
| 
								 | 
							
																	, type:		file.type
							 | 
						||
| 
								 | 
							
																	, matrix:	matrix
							 | 
						||
| 
								 | 
							
																});
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													api.Image && _inherit(api.Image, {
							 | 
						||
| 
								 | 
							
														fromDataURL: function (dataURL, size, callback){
							 | 
						||
| 
								 | 
							
															if( !api.support.dataURI || dataURL.length > 3e4 ){
							 | 
						||
| 
								 | 
							
																_makeFlashImage(
							 | 
						||
| 
								 | 
							
																	  api.extend({ scale: 'exactFit' }, size)
							 | 
						||
| 
								 | 
							
																	, dataURL.replace(/^data:[^,]+,/, '')
							 | 
						||
| 
								 | 
							
																	, function (err, el){ callback(el); }
							 | 
						||
| 
								 | 
							
																);
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
															else {
							 | 
						||
| 
								 | 
							
																this.parent(dataURL, size, callback);
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													// FileAPI.Form
							 | 
						||
| 
								 | 
							
													_inherit(api.Form.prototype, {
							 | 
						||
| 
								 | 
							
														toData: function (fn){
							 | 
						||
| 
								 | 
							
															var items = this.items, i = items.length;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															for( ; i--; ){
							 | 
						||
| 
								 | 
							
																if( items[i].file && _isHtmlFile(items[i].blob) ){
							 | 
						||
| 
								 | 
							
																	return this.parent.apply(this, arguments);
							 | 
						||
| 
								 | 
							
																}
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															api.log('FlashAPI.Form.toData');
							 | 
						||
| 
								 | 
							
															fn(items);
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													// FileAPI.XHR
							 | 
						||
| 
								 | 
							
													_inherit(api.XHR.prototype, {
							 | 
						||
| 
								 | 
							
														_send: function (options, formData){
							 | 
						||
| 
								 | 
							
															if(
							 | 
						||
| 
								 | 
							
																   formData.nodeName
							 | 
						||
| 
								 | 
							
																|| formData.append && api.support.html5
							 | 
						||
| 
								 | 
							
																|| api.isArray(formData) && (typeof formData[0] === 'string')
							 | 
						||
| 
								 | 
							
															){
							 | 
						||
| 
								 | 
							
																// HTML5, Multipart or IFrame
							 | 
						||
| 
								 | 
							
																return	this.parent.apply(this, arguments);
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															var
							 | 
						||
| 
								 | 
							
																  data = {}
							 | 
						||
| 
								 | 
							
																, files = {}
							 | 
						||
| 
								 | 
							
																, _this = this
							 | 
						||
| 
								 | 
							
																, flashId
							 | 
						||
| 
								 | 
							
																, fileId
							 | 
						||
| 
								 | 
							
															;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															_each(formData, function (item){
							 | 
						||
| 
								 | 
							
																if( item.file ){
							 | 
						||
| 
								 | 
							
																	files[item.name] = item = _getFileDescr(item.blob);
							 | 
						||
| 
								 | 
							
																	fileId  = item.id;
							 | 
						||
| 
								 | 
							
																	flashId = item.flashId;
							 | 
						||
| 
								 | 
							
																}
							 | 
						||
| 
								 | 
							
																else {
							 | 
						||
| 
								 | 
							
																	data[item.name] = item.blob;
							 | 
						||
| 
								 | 
							
																}
							 | 
						||
| 
								 | 
							
															});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															if( !fileId ){
							 | 
						||
| 
								 | 
							
																flashId = _attr;
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															if( !flashId ){
							 | 
						||
| 
								 | 
							
																api.log('[err] FlashAPI._send: flashId -- undefined');
							 | 
						||
| 
								 | 
							
																return this.parent.apply(this, arguments);
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
															else {
							 | 
						||
| 
								 | 
							
																api.log('FlashAPI.XHR._send: '+ flashId +' -> '+ fileId);
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															_this.xhr = {
							 | 
						||
| 
								 | 
							
																headers: {},
							 | 
						||
| 
								 | 
							
																abort: function (){ flash.cmd(flashId, 'abort', { id: fileId }); },
							 | 
						||
| 
								 | 
							
																getResponseHeader: function (name){ return this.headers[name]; },
							 | 
						||
| 
								 | 
							
																getAllResponseHeaders: function (){ return this.headers; }
							 | 
						||
| 
								 | 
							
															};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															var queue = api.queue(function (){
							 | 
						||
| 
								 | 
							
																flash.cmd(flashId, 'upload', {
							 | 
						||
| 
								 | 
							
																	  url: _getUrl(options.url.replace(/([a-z]+)=(\?)&?/i, ''))
							 | 
						||
| 
								 | 
							
																	, data: data
							 | 
						||
| 
								 | 
							
																	, files: fileId ? files : null
							 | 
						||
| 
								 | 
							
																	, headers: options.headers || {}
							 | 
						||
| 
								 | 
							
																	, callback: _wrap(function upload(evt){
							 | 
						||
| 
								 | 
							
																		var type = evt.type, result = evt.result;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																		api.log('FlashAPI.upload.'+type);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																		if( type == 'progress' ){
							 | 
						||
| 
								 | 
							
																			evt.loaded = Math.min(evt.loaded, evt.total); // @todo fixme
							 | 
						||
| 
								 | 
							
																			evt.lengthComputable = true;
							 | 
						||
| 
								 | 
							
																			options.progress(evt);
							 | 
						||
| 
								 | 
							
																		}
							 | 
						||
| 
								 | 
							
																		else if( type == 'complete' ){
							 | 
						||
| 
								 | 
							
																			_unwrap(upload);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																			if( typeof result == 'string' ){
							 | 
						||
| 
								 | 
							
																				_this.responseText	= result.replace(/%22/g, "\"").replace(/%5c/g, "\\").replace(/%26/g, "&").replace(/%25/g, "%");
							 | 
						||
| 
								 | 
							
																			}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																			_this.end(evt.status || 200);
							 | 
						||
| 
								 | 
							
																		}
							 | 
						||
| 
								 | 
							
																		else if( type == 'abort' || type == 'error' ){
							 | 
						||
| 
								 | 
							
																			_this.end(evt.status || 0, evt.message);
							 | 
						||
| 
								 | 
							
																			_unwrap(upload);
							 | 
						||
| 
								 | 
							
																		}
							 | 
						||
| 
								 | 
							
																	})
							 | 
						||
| 
								 | 
							
																});
							 | 
						||
| 
								 | 
							
															});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															// #2174: FileReference.load() call while FileReference.upload() or vice versa
							 | 
						||
| 
								 | 
							
															_each(files, function (file){
							 | 
						||
| 
								 | 
							
																queue.inc();
							 | 
						||
| 
								 | 
							
																api.getInfo(file, queue.next);
							 | 
						||
| 
								 | 
							
															});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															queue.check();
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													});
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										function _makeFlashHTML(opts){
							 | 
						||
| 
								 | 
							
											return ('<object id="#id#" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+(opts.width || '100%')+'" height="'+(opts.height || '100%')+'">'
							 | 
						||
| 
								 | 
							
												+ '<param name="movie" value="#src#" />'
							 | 
						||
| 
								 | 
							
												+ '<param name="flashvars" value="#flashvars#" />'
							 | 
						||
| 
								 | 
							
												+ '<param name="swliveconnect" value="true" />'
							 | 
						||
| 
								 | 
							
												+ '<param name="allowscriptaccess" value="always" />'
							 | 
						||
| 
								 | 
							
												+ '<param name="allownetworking" value="all" />'
							 | 
						||
| 
								 | 
							
												+ '<param name="menu" value="false" />'
							 | 
						||
| 
								 | 
							
												+ '<param name="wmode" value="#wmode#" />'
							 | 
						||
| 
								 | 
							
												+ '<embed flashvars="#flashvars#" swliveconnect="true" allownetworking="all" allowscriptaccess="always" name="#id#" src="#src#" width="'+(opts.width || '100%')+'" height="'+(opts.height || '100%')+'" menu="false" wmode="transparent" type="application/x-shockwave-flash"></embed>'
							 | 
						||
| 
								 | 
							
												+ '</object>').replace(/#(\w+)#/ig, function (a, name){ return opts[name]; })
							 | 
						||
| 
								 | 
							
											;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										function _css(el, css){
							 | 
						||
| 
								 | 
							
											if( el && el.style ){
							 | 
						||
| 
								 | 
							
												var key, val;
							 | 
						||
| 
								 | 
							
												for( key in css ){
							 | 
						||
| 
								 | 
							
													val = css[key];
							 | 
						||
| 
								 | 
							
													if( typeof val == 'number' ){
							 | 
						||
| 
								 | 
							
														val += 'px';
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													try { el.style[key] = val; } catch (e) {}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										function _inherit(obj, methods){
							 | 
						||
| 
								 | 
							
											_each(methods, function (fn, name){
							 | 
						||
| 
								 | 
							
												var prev = obj[name];
							 | 
						||
| 
								 | 
							
												obj[name] = function (){
							 | 
						||
| 
								 | 
							
													this.parent = prev;
							 | 
						||
| 
								 | 
							
													return fn.apply(this, arguments);
							 | 
						||
| 
								 | 
							
												};
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										function _isHtmlFile(file){
							 | 
						||
| 
								 | 
							
											return	file && !file.flashId;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										function _wrap(fn){
							 | 
						||
| 
								 | 
							
											var id = fn.wid = api.uid();
							 | 
						||
| 
								 | 
							
											flash._fn[id] = fn;
							 | 
						||
| 
								 | 
							
											return	'FileAPI.Flash._fn.'+id;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										function _unwrap(fn){
							 | 
						||
| 
								 | 
							
											try {
							 | 
						||
| 
								 | 
							
												flash._fn[fn.wid] = null;
							 | 
						||
| 
								 | 
							
												delete	flash._fn[fn.wid];
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											catch(e){}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										function _getUrl(url, params){
							 | 
						||
| 
								 | 
							
											if( !_rhttp.test(url) ){
							 | 
						||
| 
								 | 
							
												if( /^\.\//.test(url) || '/' != url.charAt(0) ){
							 | 
						||
| 
								 | 
							
													var path = location.pathname;
							 | 
						||
| 
								 | 
							
													path = path.substr(0, path.lastIndexOf('/'));
							 | 
						||
| 
								 | 
							
													url = (path +'/'+ url).replace('/./', '/');
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( '//' != url.substr(0, 2) ){
							 | 
						||
| 
								 | 
							
													url = '//' + location.host + url;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if( !_rhttp.test(url) ){
							 | 
						||
| 
								 | 
							
													url = location.protocol + url;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if( params ){
							 | 
						||
| 
								 | 
							
												url += (/\?/.test(url) ? '&' : '?') + params;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											return	url;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										function _makeFlashImage(opts, base64, fn){
							 | 
						||
| 
								 | 
							
											var
							 | 
						||
| 
								 | 
							
												  key
							 | 
						||
| 
								 | 
							
												, flashId = api.uid()
							 | 
						||
| 
								 | 
							
												, el = document.createElement('div')
							 | 
						||
| 
								 | 
							
												, attempts = 10
							 | 
						||
| 
								 | 
							
											;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											for( key in opts ){
							 | 
						||
| 
								 | 
							
												el.setAttribute(key, opts[key]);
							 | 
						||
| 
								 | 
							
												el[key] = opts[key];
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											_css(el, opts);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											opts.width	= '100%';
							 | 
						||
| 
								 | 
							
											opts.height	= '100%';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											el.innerHTML = _makeFlashHTML(api.extend({
							 | 
						||
| 
								 | 
							
												  id: flashId
							 | 
						||
| 
								 | 
							
												, src: _getUrl(api.flashImageUrl, 'r='+ api.uid())
							 | 
						||
| 
								 | 
							
												, wmode: 'opaque'
							 | 
						||
| 
								 | 
							
												, flashvars: 'scale='+ opts.scale +'&callback='+_wrap(function _(){
							 | 
						||
| 
								 | 
							
													_unwrap(_);
							 | 
						||
| 
								 | 
							
													if( --attempts > 0 ){
							 | 
						||
| 
								 | 
							
														_setImage();
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													return true;
							 | 
						||
| 
								 | 
							
												})
							 | 
						||
| 
								 | 
							
											}, opts));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											function _setImage(){
							 | 
						||
| 
								 | 
							
												try {
							 | 
						||
| 
								 | 
							
													// Get flash-object by id
							 | 
						||
| 
								 | 
							
													var img = flash.get(flashId);
							 | 
						||
| 
								 | 
							
													img.setImage(base64);
							 | 
						||
| 
								 | 
							
												} catch (e){
							 | 
						||
| 
								 | 
							
													api.log('[err] FlashAPI.Preview.setImage -- can not set "base64":', e);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											fn(false, el);
							 | 
						||
| 
								 | 
							
											el = null;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										function _getFileDescr(file){
							 | 
						||
| 
								 | 
							
											return	{
							 | 
						||
| 
								 | 
							
												  id: file.id
							 | 
						||
| 
								 | 
							
												, name: file.name
							 | 
						||
| 
								 | 
							
												, matrix: file.matrix
							 | 
						||
| 
								 | 
							
												, flashId: file.flashId
							 | 
						||
| 
								 | 
							
											};
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										function _getDimensions(el){
							 | 
						||
| 
								 | 
							
											var
							 | 
						||
| 
								 | 
							
												  box = el.getBoundingClientRect()
							 | 
						||
| 
								 | 
							
												, body = document.body
							 | 
						||
| 
								 | 
							
												, docEl = (el && el.ownerDocument).documentElement
							 | 
						||
| 
								 | 
							
											;
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											function getOffset(obj) {
							 | 
						||
| 
								 | 
							
											    var left, top;
							 | 
						||
| 
								 | 
							
											    left = top = 0;
							 | 
						||
| 
								 | 
							
											    if (obj.offsetParent) {
							 | 
						||
| 
								 | 
							
											        do {
							 | 
						||
| 
								 | 
							
											            left += obj.offsetLeft;
							 | 
						||
| 
								 | 
							
											            top  += obj.offsetTop;
							 | 
						||
| 
								 | 
							
											        } while (obj = obj.offsetParent);
							 | 
						||
| 
								 | 
							
											    }
							 | 
						||
| 
								 | 
							
											    return {
							 | 
						||
| 
								 | 
							
											        left : left,
							 | 
						||
| 
								 | 
							
											        top : top
							 | 
						||
| 
								 | 
							
											    };
							 | 
						||
| 
								 | 
							
											};
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											return {
							 | 
						||
| 
								 | 
							
												  top:		getOffset(el).top
							 | 
						||
| 
								 | 
							
												, left:		getOffset(el).left
							 | 
						||
| 
								 | 
							
												, width:	el.offsetWidth
							 | 
						||
| 
								 | 
							
												, height:	el.offsetHeight
							 | 
						||
| 
								 | 
							
											};
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// @export
							 | 
						||
| 
								 | 
							
										api.Flash = flash;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Check dataURI support
							 | 
						||
| 
								 | 
							
										api.newImage('data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==', function (err, img){
							 | 
						||
| 
								 | 
							
											api.support.dataURI = !(img.width != 1 || img.height != 1);
							 | 
						||
| 
								 | 
							
											flash.init();
							 | 
						||
| 
								 | 
							
										});
							 | 
						||
| 
								 | 
							
									})();
							 | 
						||
| 
								 | 
							
								})(window, window.jQuery, FileAPI);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * FileAPI fallback to Flash
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @flash-developer  "Vladimir Demidov" <v.demidov@corp.mail.ru>
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*global window, FileAPI */
							 | 
						||
| 
								 | 
							
								(function (window, jQuery, api) {
							 | 
						||
| 
								 | 
							
								    "use strict";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    var _each = api.each,
							 | 
						||
| 
								 | 
							
								        _cameraQueue = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (api.support.flash && (api.media && !api.support.media)) {
							 | 
						||
| 
								 | 
							
								        (function () {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            function _wrap(fn) {
							 | 
						||
| 
								 | 
							
								                var id = fn.wid = api.uid();
							 | 
						||
| 
								 | 
							
								                api.Flash._fn[id] = fn;
							 | 
						||
| 
								 | 
							
								                return 'FileAPI.Flash._fn.' + id;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            function _unwrap(fn) {
							 | 
						||
| 
								 | 
							
								                try {
							 | 
						||
| 
								 | 
							
								                    api.Flash._fn[fn.wid] = null;
							 | 
						||
| 
								 | 
							
								                    delete api.Flash._fn[fn.wid];
							 | 
						||
| 
								 | 
							
								                } catch (e) {
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            var flash = api.Flash;
							 | 
						||
| 
								 | 
							
								            api.extend(api.Flash, {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                patchCamera: function () {
							 | 
						||
| 
								 | 
							
								                    api.Camera.fallback = function (el, options, callback) {
							 | 
						||
| 
								 | 
							
								                        var camId = api.uid();
							 | 
						||
| 
								 | 
							
								                        api.log('FlashAPI.Camera.publish: ' + camId);
							 | 
						||
| 
								 | 
							
								                        flash.publish(el, camId, api.extend(options, {
							 | 
						||
| 
								 | 
							
								                            camera: true,
							 | 
						||
| 
								 | 
							
								                            onEvent: _wrap(function _(evt) {
							 | 
						||
| 
								 | 
							
								                                if (evt.type === 'camera') {
							 | 
						||
| 
								 | 
							
								                                    _unwrap(_);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                                    if (evt.error) {
							 | 
						||
| 
								 | 
							
								                                        api.log('FlashAPI.Camera.publish.error: ' + evt.error);
							 | 
						||
| 
								 | 
							
								                                        callback(evt.error);
							 | 
						||
| 
								 | 
							
								                                    } else {
							 | 
						||
| 
								 | 
							
								                                        api.log('FlashAPI.Camera.publish.success: ' + camId);
							 | 
						||
| 
								 | 
							
								                                        callback(null);
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                }
							 | 
						||
| 
								 | 
							
								                            })
							 | 
						||
| 
								 | 
							
								                        }));
							 | 
						||
| 
								 | 
							
								                    };
							 | 
						||
| 
								 | 
							
								                    // Run
							 | 
						||
| 
								 | 
							
								                    _each(_cameraQueue, function (args) {
							 | 
						||
| 
								 | 
							
								                        api.Camera.fallback.apply(api.Camera, args);
							 | 
						||
| 
								 | 
							
								                    });
							 | 
						||
| 
								 | 
							
								                    _cameraQueue = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    // FileAPI.Camera:proto
							 | 
						||
| 
								 | 
							
								                    api.extend(api.Camera.prototype, {
							 | 
						||
| 
								 | 
							
								                        _id: function () {
							 | 
						||
| 
								 | 
							
								                            return this.video.id;
							 | 
						||
| 
								 | 
							
								                        },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                        start: function (callback) {
							 | 
						||
| 
								 | 
							
								                            var _this = this;
							 | 
						||
| 
								 | 
							
								                            flash.cmd(this._id(), 'camera.on', {
							 | 
						||
| 
								 | 
							
								                                callback: _wrap(function _(evt) {
							 | 
						||
| 
								 | 
							
								                                    _unwrap(_);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                                    if (evt.error) {
							 | 
						||
| 
								 | 
							
								                                        api.log('FlashAPI.camera.on.error: ' + evt.error);
							 | 
						||
| 
								 | 
							
								                                        callback(evt.error, _this);
							 | 
						||
| 
								 | 
							
								                                    } else {
							 | 
						||
| 
								 | 
							
								                                        api.log('FlashAPI.camera.on.success: ' + _this._id());
							 | 
						||
| 
								 | 
							
								                                        _this._active = true;
							 | 
						||
| 
								 | 
							
								                                        callback(null, _this);
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                })
							 | 
						||
| 
								 | 
							
								                            });
							 | 
						||
| 
								 | 
							
								                        },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                        stop: function () {
							 | 
						||
| 
								 | 
							
								                            this._active = false;
							 | 
						||
| 
								 | 
							
								                            flash.cmd(this._id(), 'camera.off');
							 | 
						||
| 
								 | 
							
								                        },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                        shot: function () {
							 | 
						||
| 
								 | 
							
								                            api.log('FlashAPI.Camera.shot:', this._id());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                            var shot = api.Flash.cmd(this._id(), 'shot', {});
							 | 
						||
| 
								 | 
							
								                            shot.type = 'image/png';
							 | 
						||
| 
								 | 
							
								                            shot.flashId = this._id();
							 | 
						||
| 
								 | 
							
								                            shot.isShot = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                            return new api.Camera.Shot(shot);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                    });
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            api.Camera.fallback = function () {
							 | 
						||
| 
								 | 
							
								                _cameraQueue.push(arguments);
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        }());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}(window, window.jQuery, FileAPI));
							 | 
						||
| 
								 | 
							
								if( typeof define === "function" && define.amd ){ define("FileAPI", [], function (){ return FileAPI; }); }
							 |