/*! WebUploader 0.1.5 */ /** * @fileOverview 璁╁唴閮ㄥ悇涓儴浠剁殑浠g爜鍙互鐢╗amd](https://github.com/amdjs/amdjs-api/wiki/AMD)妯″潡瀹氫箟鏂瑰紡缁勭粐璧锋潵銆 * * AMD API 鍐呴儴鐨勭畝鍗曚笉瀹屽叏瀹炵幇锛岃蹇界暐銆傚彧鏈夊綋WebUploader琚悎骞舵垚涓€涓枃浠剁殑鏃跺€欐墠浼氬紩鍏ャ€ */ (function( root, factory ) { var modules = {}, // 鍐呴儴require, 绠€鍗曚笉瀹屽叏瀹炵幇銆 // https://github.com/amdjs/amdjs-api/wiki/require _require = function( deps, callback ) { var args, len, i; // 濡傛灉deps涓嶆槸鏁扮粍锛屽垯鐩存帴杩斿洖鎸囧畾module if ( typeof deps === 'string' ) { return getModule( deps ); } else { args = []; for( len = deps.length, i = 0; i < len; i++ ) { args.push( getModule( deps[ i ] ) ); } return callback.apply( null, args ); } }, // 鍐呴儴define锛屾殏鏃朵笉鏀寔涓嶆寚瀹歩d. _define = function( id, deps, factory ) { if ( arguments.length === 2 ) { factory = deps; deps = null; } _require( deps || [], function() { setModule( id, factory, arguments ); }); }, // 璁剧疆module, 鍏煎CommonJs鍐欐硶銆 setModule = function( id, factory, args ) { var module = { exports: factory }, returned; if ( typeof factory === 'function' ) { args.length || (args = [ _require, module.exports, module ]); returned = factory.apply( null, args ); returned !== undefined && (module.exports = returned); } modules[ id ] = module.exports; }, // 鏍规嵁id鑾峰彇module getModule = function( id ) { var module = modules[ id ] || root[ id ]; if ( !module ) { throw new Error( '`' + id + '` is undefined' ); } return module; }, // 灏嗘墍鏈塵odules锛屽皢璺緞ids瑁呮崲鎴愬璞°€ exportsTo = function( obj ) { var key, host, parts, part, last, ucFirst; // make the first character upper case. ucFirst = function( str ) { return str && (str.charAt( 0 ).toUpperCase() + str.substr( 1 )); }; for ( key in modules ) { host = obj; if ( !modules.hasOwnProperty( key ) ) { continue; } parts = key.split('/'); last = ucFirst( parts.pop() ); while( (part = ucFirst( parts.shift() )) ) { host[ part ] = host[ part ] || {}; host = host[ part ]; } host[ last ] = modules[ key ]; } return obj; }, makeExport = function( dollar ) { root.__dollar = dollar; // exports every module. return exportsTo( factory( root, _define, _require ) ); }, origin; if ( typeof module === 'object' && typeof module.exports === 'object' ) { // For CommonJS and CommonJS-like environments where a proper window is present, module.exports = makeExport(); } else if (typeof define === 'function' && define.amd ) { // Allow using this built library as an AMD module // in another project. That other project will only // see this AMD call, not the internal modules in // the closure below. define([ 'jquery' ], makeExport ); } else { // Browser globals case. Just assign the // result to a property on the global. origin = root.WebUploader; root.WebUploader = makeExport(); root.WebUploader.noConflict = function() { root.WebUploader = origin; }; } })( window, function( window, define, require ) { /** * @fileOverview jQuery or Zepto */ define('dollar-third',[],function() { var $ = window.__dollar || window.jQuery || window.Zepto; if ( !$ ) { throw new Error('jQuery or Zepto not found!'); } return $; }); /** * @fileOverview Dom 鎿嶄綔鐩稿叧 */ define('dollar',[ 'dollar-third' ], function( _ ) { return _; }); /** * @fileOverview 浣跨敤jQuery鐨凱romise */ define('promise-third',[ 'dollar' ], function( $ ) { return { Deferred: $.Deferred, when: $.when, isPromise: function( anything ) { return anything && typeof anything.then === 'function'; } }; }); /** * @fileOverview Promise/A+ */ define('promise',[ 'promise-third' ], function( _ ) { return _; }); /** * @fileOverview 鍩虹绫绘柟娉曘€ */ /** * Web Uploader鍐呴儴绫荤殑璇︾粏璇存槑锛屼互涓嬫彁鍙婄殑鍔熻兘绫伙紝閮藉彲浠ュ湪`WebUploader`杩欎釜鍙橀噺涓闂埌銆 * * As you know, Web Uploader鐨勬瘡涓枃浠堕兘鏄敤杩嘯AMD](https://github.com/amdjs/amdjs-api/wiki/AMD)瑙勮寖涓殑`define`缁勭粐璧锋潵鐨? 姣忎釜Module閮戒細鏈変釜module id. * 榛樿module id涓鸿鏂囦欢鐨勮矾寰勶紝鑰屾璺緞灏嗕細杞寲鎴愬悕瀛楃┖闂村瓨鏀惧湪WebUploader涓€傚锛 * * * module `base`锛歐ebUploader.Base * * module `file`: WebUploader.File * * module `lib/dnd`: WebUploader.Lib.Dnd * * module `runtime/html5/dnd`: WebUploader.Runtime.Html5.Dnd * * * 浠ヤ笅鏂囨。涓绫荤殑浣跨敤鍙兘鐪佺暐鎺変簡`WebUploader`鍓嶇紑銆 * @module WebUploader * @title WebUploader API鏂囨。 */ define('base',[ 'dollar', 'promise' ], function( $, promise ) { var noop = function() {}, call = Function.call; // http://jsperf.com/uncurrythis // 鍙嶇閲屽寲 function uncurryThis( fn ) { return function() { return call.apply( fn, arguments ); }; } function bindFn( fn, context ) { return function() { return fn.apply( context, arguments ); }; } function createObject( proto ) { var f; if ( Object.create ) { return Object.create( proto ); } else { f = function() {}; f.prototype = proto; return new f(); } } /** * 鍩虹绫伙紝鎻愪緵涓€浜涚畝鍗曞父鐢ㄧ殑鏂规硶銆 * @class Base */ return { /** * @property {String} version 褰撳墠鐗堟湰鍙枫€ */ version: '0.1.5', /** * @property {jQuery|Zepto} $ 寮曠敤渚濊禆鐨刯Query鎴栬€匷epto瀵硅薄銆 */ $: $, Deferred: promise.Deferred, isPromise: promise.isPromise, when: promise.when, /** * @description 绠€鍗曠殑娴忚鍣ㄦ鏌ョ粨鏋溿€ * * * `webkit` webkit鐗堟湰鍙凤紝濡傛灉娴忚鍣ㄤ负闈瀢ebkit鍐呮牳锛屾灞炴€т负`undefined`銆 * * `chrome` chrome娴忚鍣ㄧ増鏈彿锛屽鏋滄祻瑙堝櫒涓篶hrome锛屾灞炴€т负`undefined`銆 * * `ie` ie娴忚鍣ㄧ増鏈彿锛屽鏋滄祻瑙堝櫒涓洪潪ie锛屾灞炴€т负`undefined`銆?*鏆備笉鏀寔ie10+** * * `firefox` firefox娴忚鍣ㄧ増鏈彿锛屽鏋滄祻瑙堝櫒涓洪潪firefox锛屾灞炴€т负`undefined`銆 * * `safari` safari娴忚鍣ㄧ増鏈彿锛屽鏋滄祻瑙堝櫒涓洪潪safari锛屾灞炴€т负`undefined`銆 * * `opera` opera娴忚鍣ㄧ増鏈彿锛屽鏋滄祻瑙堝櫒涓洪潪opera锛屾灞炴€т负`undefined`銆 * * @property {Object} [browser] */ browser: (function( ua ) { var ret = {}, webkit = ua.match( /WebKit\/([\d.]+)/ ), chrome = ua.match( /Chrome\/([\d.]+)/ ) || ua.match( /CriOS\/([\d.]+)/ ), ie = ua.match( /MSIE\s([\d\.]+)/ ) || ua.match( /(?:trident)(?:.*rv:([\w.]+))?/i ), firefox = ua.match( /Firefox\/([\d.]+)/ ), safari = ua.match( /Safari\/([\d.]+)/ ), opera = ua.match( /OPR\/([\d.]+)/ ); webkit && (ret.webkit = parseFloat( webkit[ 1 ] )); chrome && (ret.chrome = parseFloat( chrome[ 1 ] )); ie && (ret.ie = parseFloat( ie[ 1 ] )); firefox && (ret.firefox = parseFloat( firefox[ 1 ] )); safari && (ret.safari = parseFloat( safari[ 1 ] )); opera && (ret.opera = parseFloat( opera[ 1 ] )); return ret; })( navigator.userAgent ), /** * @description 鎿嶄綔绯荤粺妫€鏌ョ粨鏋溿€ * * * `android` 濡傛灉鍦╝ndroid娴忚鍣ㄧ幆澧冧笅锛屾鍊间负瀵瑰簲鐨刟ndroid鐗堟湰鍙凤紝鍚﹀垯涓篳undefined`銆 * * `ios` 濡傛灉鍦╥os娴忚鍣ㄧ幆澧冧笅锛屾鍊间负瀵瑰簲鐨刬os鐗堟湰鍙凤紝鍚﹀垯涓篳undefined`銆 * @property {Object} [os] */ os: (function( ua ) { var ret = {}, // osx = !!ua.match( /\(Macintosh\; Intel / ), android = ua.match( /(?:Android);?[\s\/]+([\d.]+)?/ ), ios = ua.match( /(?:iPad|iPod|iPhone).*OS\s([\d_]+)/ ); // osx && (ret.osx = true); android && (ret.android = parseFloat( android[ 1 ] )); ios && (ret.ios = parseFloat( ios[ 1 ].replace( /_/g, '.' ) )); return ret; })( navigator.userAgent ), /** * 瀹炵幇绫讳笌绫讳箣闂寸殑缁ф壙銆 * @method inherits * @grammar Base.inherits( super ) => child * @grammar Base.inherits( super, protos ) => child * @grammar Base.inherits( super, protos, statics ) => child * @param {Class} super 鐖剁被 * @param {Object | Function} [protos] 瀛愮被鎴栬€呭璞°€傚鏋滃璞′腑鍖呭惈constructor锛屽瓙绫诲皢鏄敤姝ゅ睘鎬у€笺€ * @param {Function} [protos.constructor] 瀛愮被鏋勯€犲櫒锛屼笉鎸囧畾鐨勮瘽灏嗗垱寤轰釜涓存椂鐨勭洿鎺ユ墽琛岀埗绫绘瀯閫犲櫒鐨勬柟娉曘€ * @param {Object} [statics] 闈欐€佸睘鎬ф垨鏂规硶銆 * @return {Class} 杩斿洖瀛愮被銆 * @example * function Person() { * console.log( 'Super' ); * } * Person.prototype.hello = function() { * console.log( 'hello' ); * }; * * var Manager = Base.inherits( Person, { * world: function() { * console.log( 'World' ); * } * }); * * // 鍥犱负娌℃湁鎸囧畾鏋勯€犲櫒锛岀埗绫荤殑鏋勯€犲櫒灏嗕細鎵ц銆 * var instance = new Manager(); // => Super * * // 缁ф壙瀛愮埗绫荤殑鏂规硶 * instance.hello(); // => hello * instance.world(); // => World * * // 瀛愮被鐨刜_super__灞炴€ф寚鍚戠埗绫 * console.log( Manager.__super__ === Person ); // => true */ inherits: function( Super, protos, staticProtos ) { var child; if ( typeof protos === 'function' ) { child = protos; protos = null; } else if ( protos && protos.hasOwnProperty('constructor') ) { child = protos.constructor; } else { child = function() { return Super.apply( this, arguments ); }; } // 澶嶅埗闈欐€佹柟娉 $.extend( true, child, Super, staticProtos || {} ); /* jshint camelcase: false */ // 璁╁瓙绫荤殑__super__灞炴€ф寚鍚戠埗绫汇€ child.__super__ = Super.prototype; // 鏋勫缓鍘熷瀷锛屾坊鍔犲師鍨嬫柟娉曟垨灞炴€с€ // 鏆傛椂鐢∣bject.create瀹炵幇銆 child.prototype = createObject( Super.prototype ); protos && $.extend( true, child.prototype, protos ); return child; }, /** * 涓€涓笉鍋氫换浣曚簨鎯呯殑鏂规硶銆傚彲浠ョ敤鏉ヨ祴鍊肩粰榛樿鐨刢allback. * @method noop */ noop: noop, /** * 杩斿洖涓€涓柊鐨勬柟娉曪紝姝ゆ柟娉曞皢宸叉寚瀹氱殑`context`鏉ユ墽琛屻€ * @grammar Base.bindFn( fn, context ) => Function * @method bindFn * @example * var doSomething = function() { * console.log( this.name ); * }, * obj = { * name: 'Object Name' * }, * aliasFn = Base.bind( doSomething, obj ); * * aliasFn(); // => Object Name * */ bindFn: bindFn, /** * 寮曠敤Console.log濡傛灉瀛樺湪鐨勮瘽锛屽惁鍒欏紩鐢ㄤ竴涓猍绌哄嚱鏁皀oop](#WebUploader:Base.noop)銆 * @grammar Base.log( args... ) => undefined * @method log */ log: (function() { if ( window.console ) { return bindFn( console.log, console ); } return noop; })(), nextTick: (function() { return function( cb ) { setTimeout( cb, 1 ); }; // @bug 褰撴祻瑙堝櫒涓嶅湪褰撳墠绐楀彛鏃跺氨鍋滀簡銆 // var next = window.requestAnimationFrame || // window.webkitRequestAnimationFrame || // window.mozRequestAnimationFrame || // function( cb ) { // window.setTimeout( cb, 1000 / 60 ); // }; // // fix: Uncaught TypeError: Illegal invocation // return bindFn( next, window ); })(), /** * 琚玔uncurrythis](http://www.2ality.com/2011/11/uncurrying-this.html)鐨勬暟缁剆lice鏂规硶銆 * 灏嗙敤鏉ュ皢闈炴暟缁勫璞¤浆鍖栨垚鏁扮粍瀵硅薄銆 * @grammar Base.slice( target, start[, end] ) => Array * @method slice * @example * function doSomthing() { * var args = Base.slice( arguments, 1 ); * console.log( args ); * } * * doSomthing( 'ignored', 'arg2', 'arg3' ); // => Array ["arg2", "arg3"] */ slice: uncurryThis( [].slice ), /** * 鐢熸垚鍞竴鐨処D * @method guid * @grammar Base.guid() => String * @grammar Base.guid( prefx ) => String */ guid: (function() { var counter = 0; return function( prefix ) { var guid = (+new Date()).toString( 32 ), i = 0; for ( ; i < 5; i++ ) { guid += Math.floor( Math.random() * 65535 ).toString( 32 ); } return (prefix || 'wu_') + guid + (counter++).toString( 32 ); }; })(), /** * 鏍煎紡鍖栨枃浠跺ぇ灏? 杈撳嚭鎴愬甫鍗曚綅鐨勫瓧绗︿覆 * @method formatSize * @grammar Base.formatSize( size ) => String * @grammar Base.formatSize( size, pointLength ) => String * @grammar Base.formatSize( size, pointLength, units ) => String * @param {Number} size 鏂囦欢澶у皬 * @param {Number} [pointLength=2] 绮剧‘鍒扮殑灏忔暟鐐规暟銆 * @param {Array} [units=[ 'B', 'K', 'M', 'G', 'TB' ]] 鍗曚綅鏁扮粍銆備粠瀛楄妭锛屽埌鍗冨瓧鑺傦紝涓€鐩村線涓婃寚瀹氥€傚鏋滃崟浣嶆暟缁勯噷闈㈠彧鎸囧畾浜嗗埌浜咾(鍗冨瓧鑺?锛屽悓鏃舵枃浠跺ぇ灏忓ぇ浜嶮, 姝ゆ柟娉曠殑杈撳嚭灏嗚繕鏄樉绀烘垚澶氬皯K. * @example * console.log( Base.formatSize( 100 ) ); // => 100B * console.log( Base.formatSize( 1024 ) ); // => 1.00K * console.log( Base.formatSize( 1024, 0 ) ); // => 1K * console.log( Base.formatSize( 1024 * 1024 ) ); // => 1.00M * console.log( Base.formatSize( 1024 * 1024 * 1024 ) ); // => 1.00G * console.log( Base.formatSize( 1024 * 1024 * 1024, 0, ['B', 'KB', 'MB'] ) ); // => 1024MB */ formatSize: function( size, pointLength, units ) { var unit; units = units || [ 'B', 'K', 'M', 'G', 'TB' ]; while ( (unit = units.shift()) && size > 1024 ) { size = size / 1024; } return (unit === 'B' ? size : size.toFixed( pointLength || 2 )) + unit; } }; }); /** * 浜嬩欢澶勭悊绫伙紝鍙互鐙珛浣跨敤锛屼篃鍙互鎵╁睍缁欏璞′娇鐢ㄣ€ * @fileOverview Mediator */ define('mediator',[ 'base' ], function( Base ) { var $ = Base.$, slice = [].slice, separator = /\s+/, protos; // 鏍规嵁鏉′欢杩囨护鍑轰簨浠秇andlers. function findHandlers( arr, name, callback, context ) { return $.grep( arr, function( handler ) { return handler && (!name || handler.e === name) && (!callback || handler.cb === callback || handler.cb._cb === callback) && (!context || handler.ctx === context); }); } function eachEvent( events, callback, iterator ) { // 涓嶆敮鎸佸璞★紝鍙敮鎸佸涓猠vent鐢ㄧ┖鏍奸殧寮€ $.each( (events || '').split( separator ), function( _, key ) { iterator( key, callback ); }); } function triggerHanders( events, args ) { var stoped = false, i = -1, len = events.length, handler; while ( ++i < len ) { handler = events[ i ]; if ( handler.cb.apply( handler.ctx2, args ) === false ) { stoped = true; break; } } return !stoped; } protos = { /** * 缁戝畾浜嬩欢銆 * * `callback`鏂规硶鍦ㄦ墽琛屾椂锛宎rguments灏嗕細鏉ユ簮浜巘rigger鐨勬椂鍊欐惡甯︾殑鍙傛暟銆傚 * ```javascript * var obj = {}; * * // 浣垮緱obj鏈変簨浠惰涓 * Mediator.installTo( obj ); * * obj.on( 'testa', function( arg1, arg2 ) { * console.log( arg1, arg2 ); // => 'arg1', 'arg2' * }); * * obj.trigger( 'testa', 'arg1', 'arg2' ); * ``` * * 濡傛灉`callback`涓紝鏌愪竴涓柟娉昤return false`浜嗭紝鍒欏悗缁殑鍏朵粬`callback`閮戒笉浼氳鎵ц鍒般€ * 鍒囦細褰卞搷鍒癭trigger`鏂规硶鐨勮繑鍥炲€硷紝涓篳false`銆 * * `on`杩樺彲浠ョ敤鏉ユ坊鍔犱竴涓壒娈婁簨浠禶all`, 杩欐牱鎵€鏈夌殑浜嬩欢瑙﹀彂閮戒細鍝嶅簲鍒般€傚悓鏃舵绫籤callback`涓殑arguments鏈変竴涓笉鍚屽锛 * 灏辨槸绗竴涓弬鏁颁负`type`锛岃褰曞綋鍓嶆槸浠€涔堜簨浠跺湪瑙﹀彂銆傛绫籤callback`鐨勪紭鍏堢骇姣旇剼浣庯紝浼氬啀姝e父`callback`鎵ц瀹屽悗瑙﹀彂銆 * ```javascript * obj.on( 'all', function( type, arg1, arg2 ) { * console.log( type, arg1, arg2 ); // => 'testa', 'arg1', 'arg2' * }); * ``` * * @method on * @grammar on( name, callback[, context] ) => self * @param {String} name 浜嬩欢鍚嶏紝鏀寔澶氫釜浜嬩欢鐢ㄧ┖鏍奸殧寮€ * @param {Function} callback 浜嬩欢澶勭悊鍣 * @param {Object} [context] 浜嬩欢澶勭悊鍣ㄧ殑涓婁笅鏂囥€ * @return {self} 杩斿洖鑷韩锛屾柟渚块摼寮 * @chainable * @class Mediator */ on: function( name, callback, context ) { var me = this, set; if ( !callback ) { return this; } set = this._events || (this._events = []); eachEvent( name, callback, function( name, callback ) { var handler = { e: name }; handler.cb = callback; handler.ctx = context; handler.ctx2 = context || me; handler.id = set.length; set.push( handler ); }); return this; }, /** * 缁戝畾浜嬩欢锛屼笖褰揾andler鎵ц瀹屽悗锛岃嚜鍔ㄨВ闄ょ粦瀹氥€ * @method once * @grammar once( name, callback[, context] ) => self * @param {String} name 浜嬩欢鍚 * @param {Function} callback 浜嬩欢澶勭悊鍣 * @param {Object} [context] 浜嬩欢澶勭悊鍣ㄧ殑涓婁笅鏂囥€ * @return {self} 杩斿洖鑷韩锛屾柟渚块摼寮 * @chainable */ once: function( name, callback, context ) { var me = this; if ( !callback ) { return me; } eachEvent( name, callback, function( name, callback ) { var once = function() { me.off( name, once ); return callback.apply( context || me, arguments ); }; once._cb = callback; me.on( name, once, context ); }); return me; }, /** * 瑙i櫎浜嬩欢缁戝畾 * @method off * @grammar off( [name[, callback[, context] ] ] ) => self * @param {String} [name] 浜嬩欢鍚 * @param {Function} [callback] 浜嬩欢澶勭悊鍣 * @param {Object} [context] 浜嬩欢澶勭悊鍣ㄧ殑涓婁笅鏂囥€ * @return {self} 杩斿洖鑷韩锛屾柟渚块摼寮 * @chainable */ off: function( name, cb, ctx ) { var events = this._events; if ( !events ) { return this; } if ( !name && !cb && !ctx ) { this._events = []; return this; } eachEvent( name, cb, function( name, cb ) { $.each( findHandlers( events, name, cb, ctx ), function() { delete events[ this.id ]; }); }); return this; }, /** * 瑙﹀彂浜嬩欢 * @method trigger * @grammar trigger( name[, args...] ) => self * @param {String} type 浜嬩欢鍚 * @param {*} [...] 浠绘剰鍙傛暟 * @return {Boolean} 濡傛灉handler涓璻eturn false浜嗭紝鍒欒繑鍥瀎alse, 鍚﹀垯杩斿洖true */ trigger: function( type ) { var args, events, allEvents; if ( !this._events || !type ) { return this; } args = slice.call( arguments, 1 ); events = findHandlers( this._events, type ); allEvents = findHandlers( this._events, 'all' ); return triggerHanders( events, args ) && triggerHanders( allEvents, arguments ); } }; /** * 涓粙鑰咃紝瀹冩湰韬槸涓崟渚嬶紝浣嗗彲浠ラ€氳繃[installTo](#WebUploader:Mediator:installTo)鏂规硶锛屼娇浠讳綍瀵硅薄鍏峰浜嬩欢琛屼负銆 * 涓昏鐩殑鏄礋璐fā鍧椾笌妯″潡涔嬮棿鐨勫悎浣滐紝闄嶄綆鑰﹀悎搴︺€ * * @class Mediator */ return $.extend({ /** * 鍙互閫氳繃杩欎釜鎺ュ彛锛屼娇浠讳綍瀵硅薄鍏峰浜嬩欢鍔熻兘銆 * @method installTo * @param {Object} obj 闇€瑕佸叿澶囦簨浠惰涓虹殑瀵硅薄銆 * @return {Object} 杩斿洖obj. */ installTo: function( obj ) { return $.extend( obj, protos ); } }, protos ); }); /** * @fileOverview Uploader涓婁紶绫 */ define('uploader',[ 'base', 'mediator' ], function( Base, Mediator ) { var $ = Base.$; /** * 涓婁紶鍏ュ彛绫汇€ * @class Uploader * @constructor * @grammar new Uploader( opts ) => Uploader * @example * var uploader = WebUploader.Uploader({ * swf: 'path_of_swf/Uploader.swf', * * // 寮€璧峰垎鐗囦笂浼犮€ * chunked: true * }); */ function Uploader( opts ) { this.options = $.extend( true, {}, Uploader.options, opts ); this._init( this.options ); } // default Options // widgets涓湁鐩稿簲鎵╁睍 Uploader.options = {}; Mediator.installTo( Uploader.prototype ); // 鎵归噺娣诲姞绾懡浠ゅ紡鏂规硶銆 $.each({ upload: 'start-upload', stop: 'stop-upload', getFile: 'get-file', getFiles: 'get-files', addFile: 'add-file', addFiles: 'add-file', sort: 'sort-files', removeFile: 'remove-file', cancelFile: 'cancel-file', skipFile: 'skip-file', retry: 'retry', isInProgress: 'is-in-progress', makeThumb: 'make-thumb', md5File: 'md5-file', getDimension: 'get-dimension', addButton: 'add-btn', predictRuntimeType: 'predict-runtime-type', refresh: 'refresh', disable: 'disable', enable: 'enable', reset: 'reset' }, function( fn, command ) { Uploader.prototype[ fn ] = function() { return this.request( command, arguments ); }; }); $.extend( Uploader.prototype, { state: 'pending', _init: function( opts ) { var me = this; me.request( 'init', opts, function() { me.state = 'ready'; me.trigger('ready'); }); }, /** * 鑾峰彇鎴栬€呰缃甎ploader閰嶇疆椤广€ * @method option * @grammar option( key ) => * * @grammar option( key, val ) => self * @example * * // 鍒濆鐘舵€佸浘鐗囦笂浼犲墠涓嶄細鍘嬬缉 * var uploader = new WebUploader.Uploader({ * compress: null; * }); * * // 淇敼鍚庡浘鐗囦笂浼犲墠锛屽皾璇曞皢鍥剧墖鍘嬬缉鍒?600 * 1600 * uploader.option( 'compress', { * width: 1600, * height: 1600 * }); */ option: function( key, val ) { var opts = this.options; // setter if ( arguments.length > 1 ) { if ( $.isPlainObject( val ) && $.isPlainObject( opts[ key ] ) ) { $.extend( opts[ key ], val ); } else { opts[ key ] = val; } } else { // getter return key ? opts[ key ] : opts; } }, /** * 鑾峰彇鏂囦欢缁熻淇℃伅銆傝繑鍥炰竴涓寘鍚竴涓嬩俊鎭殑瀵硅薄銆 * * `successNum` 涓婁紶鎴愬姛鐨勬枃浠舵暟 * * `progressNum` 涓婁紶涓殑鏂囦欢鏁 * * `cancelNum` 琚垹闄ょ殑鏂囦欢鏁 * * `invalidNum` 鏃犳晥鐨勬枃浠舵暟 * * `uploadFailNum` 涓婁紶澶辫触鐨勬枃浠舵暟 * * `queueNum` 杩樺湪闃熷垪涓殑鏂囦欢鏁 * * `interruptNum` 琚殏鍋滅殑鏂囦欢鏁 * @method getStats * @grammar getStats() => Object */ getStats: function() { // return this._mgr.getStats.apply( this._mgr, arguments ); var stats = this.request('get-stats'); return stats ? { successNum: stats.numOfSuccess, progressNum: stats.numOfProgress, // who care? // queueFailNum: 0, cancelNum: stats.numOfCancel, invalidNum: stats.numOfInvalid, uploadFailNum: stats.numOfUploadFailed, queueNum: stats.numOfQueue, interruptNum: stats.numofInterrupt } : {}; }, // 闇€瑕侀噸鍐欐鏂规硶鏉ユ潵鏀寔opts.onEvent鍜宨nstance.onEvent鐨勫鐞嗗櫒 trigger: function( type/*, args...*/ ) { var args = [].slice.call( arguments, 1 ), opts = this.options, name = 'on' + type.substring( 0, 1 ).toUpperCase() + type.substring( 1 ); if ( // 璋冪敤閫氳繃on鏂规硶娉ㄥ唽鐨刪andler. Mediator.trigger.apply( this, arguments ) === false || // 璋冪敤opts.onEvent $.isFunction( opts[ name ] ) && opts[ name ].apply( this, args ) === false || // 璋冪敤this.onEvent $.isFunction( this[ name ] ) && this[ name ].apply( this, args ) === false || // 骞挎挱鎵€鏈塽ploader鐨勪簨浠躲€ Mediator.trigger.apply( Mediator, [ this, type ].concat( args ) ) === false ) { return false; } return true; }, /** * 閿€姣 webuploader 瀹炰緥 * @method destroy * @grammar destroy() => undefined */ destroy: function() { this.request( 'destroy', arguments ); this.off(); }, // widgets/widget.js灏嗚ˉ鍏呮鏂规硶鐨勮缁嗘枃妗c€ request: Base.noop }); /** * 鍒涘缓Uploader瀹炰緥锛岀瓑鍚屼簬new Uploader( opts ); * @method create * @class Base * @static * @grammar Base.create( opts ) => Uploader */ Base.create = Uploader.create = function( opts ) { return new Uploader( opts ); }; // 鏆撮湶Uploader锛屽彲浠ラ€氳繃瀹冩潵鎵╁睍涓氬姟閫昏緫銆 Base.Uploader = Uploader; return Uploader; }); /** * @fileOverview Runtime绠$悊鍣紝璐熻矗Runtime鐨勯€夋嫨, 杩炴帴 */ define('runtime/runtime',[ 'base', 'mediator' ], function( Base, Mediator ) { var $ = Base.$, factories = {}, // 鑾峰彇瀵硅薄鐨勭涓€涓猭ey getFirstKey = function( obj ) { for ( var key in obj ) { if ( obj.hasOwnProperty( key ) ) { return key; } } return null; }; // 鎺ュ彛绫汇€ function Runtime( options ) { this.options = $.extend({ container: document.body }, options ); this.uid = Base.guid('rt_'); } $.extend( Runtime.prototype, { getContainer: function() { var opts = this.options, parent, container; if ( this._container ) { return this._container; } parent = $( opts.container || document.body ); container = $( document.createElement('div') ); container.attr( 'id', 'rt_' + this.uid ); container.css({ position: 'absolute', top: '0px', left: '0px', width: '1px', height: '1px', overflow: 'hidden' }); parent.append( container ); parent.addClass('webuploader-container'); this._container = container; this._parent = parent; return container; }, init: Base.noop, exec: Base.noop, destroy: function() { this._container && this._container.remove(); this._parent && this._parent.removeClass('webuploader-container'); this.off(); } }); Runtime.orders = 'html5,flash'; /** * 娣诲姞Runtime瀹炵幇銆 * @param {String} type 绫诲瀷 * @param {Runtime} factory 鍏蜂綋Runtime瀹炵幇銆 */ Runtime.addRuntime = function( type, factory ) { factories[ type ] = factory; }; Runtime.hasRuntime = function( type ) { return !!(type ? factories[ type ] : getFirstKey( factories )); }; Runtime.create = function( opts, orders ) { var type, runtime; orders = orders || Runtime.orders; $.each( orders.split( /\s*,\s*/g ), function() { if ( factories[ this ] ) { type = this; return false; } }); type = type || getFirstKey( factories ); if ( !type ) { throw new Error('Runtime Error'); } runtime = new factories[ type ]( opts ); return runtime; }; Mediator.installTo( Runtime.prototype ); return Runtime; }); /** * @fileOverview Runtime绠$悊鍣紝璐熻矗Runtime鐨勯€夋嫨, 杩炴帴 */ define('runtime/client',[ 'base', 'mediator', 'runtime/runtime' ], function( Base, Mediator, Runtime ) { var cache; cache = (function() { var obj = {}; return { add: function( runtime ) { obj[ runtime.uid ] = runtime; }, get: function( ruid, standalone ) { var i; if ( ruid ) { return obj[ ruid ]; } for ( i in obj ) { // 鏈変簺绫诲瀷涓嶈兘閲嶇敤锛屾瘮濡俧ilepicker. if ( standalone && obj[ i ].__standalone ) { continue; } return obj[ i ]; } return null; }, remove: function( runtime ) { delete obj[ runtime.uid ]; } }; })(); function RuntimeClient( component, standalone ) { var deferred = Base.Deferred(), runtime; this.uid = Base.guid('client_'); // 鍏佽runtime娌℃湁鍒濆鍖栦箣鍓嶏紝娉ㄥ唽涓€浜涙柟娉曞湪鍒濆鍖栧悗鎵ц銆 this.runtimeReady = function( cb ) { return deferred.done( cb ); }; this.connectRuntime = function( opts, cb ) { // already connected. if ( runtime ) { throw new Error('already connected!'); } deferred.done( cb ); if ( typeof opts === 'string' && cache.get( opts ) ) { runtime = cache.get( opts ); } // 鍍廸ilePicker鍙兘鐙珛瀛樺湪锛屼笉鑳藉叕鐢ㄣ€ runtime = runtime || cache.get( null, standalone ); // 闇€瑕佸垱寤 if ( !runtime ) { runtime = Runtime.create( opts, opts.runtimeOrder ); runtime.__promise = deferred.promise(); runtime.once( 'ready', deferred.resolve ); runtime.init(); cache.add( runtime ); runtime.__client = 1; } else { // 鏉ヨ嚜cache Base.$.extend( runtime.options, opts ); runtime.__promise.then( deferred.resolve ); runtime.__client++; } standalone && (runtime.__standalone = standalone); return runtime; }; this.getRuntime = function() { return runtime; }; this.disconnectRuntime = function() { if ( !runtime ) { return; } runtime.__client--; if ( runtime.__client <= 0 ) { cache.remove( runtime ); delete runtime.__promise; runtime.destroy(); } runtime = null; }; this.exec = function() { if ( !runtime ) { return; } var args = Base.slice( arguments ); component && args.unshift( component ); return runtime.exec.apply( this, args ); }; this.getRuid = function() { return runtime && runtime.uid; }; this.destroy = (function( destroy ) { return function() { destroy && destroy.apply( this, arguments ); this.trigger('destroy'); this.off(); this.exec('destroy'); this.disconnectRuntime(); }; })( this.destroy ); } Mediator.installTo( RuntimeClient.prototype ); return RuntimeClient; }); /** * @fileOverview 閿欒淇℃伅 */ define('lib/dnd',[ 'base', 'mediator', 'runtime/client' ], function( Base, Mediator, RuntimeClent ) { var $ = Base.$; function DragAndDrop( opts ) { opts = this.options = $.extend({}, DragAndDrop.options, opts ); opts.container = $( opts.container ); if ( !opts.container.length ) { return; } RuntimeClent.call( this, 'DragAndDrop' ); } DragAndDrop.options = { accept: null, disableGlobalDnd: false }; Base.inherits( RuntimeClent, { constructor: DragAndDrop, init: function() { var me = this; me.connectRuntime( me.options, function() { me.exec('init'); me.trigger('ready'); }); } }); Mediator.installTo( DragAndDrop.prototype ); return DragAndDrop; }); /** * @fileOverview 缁勪欢鍩虹被銆 */ define('widgets/widget',[ 'base', 'uploader' ], function( Base, Uploader ) { var $ = Base.$, _init = Uploader.prototype._init, _destroy = Uploader.prototype.destroy, IGNORE = {}, widgetClass = []; function isArrayLike( obj ) { if ( !obj ) { return false; } var length = obj.length, type = $.type( obj ); if ( obj.nodeType === 1 && length ) { return true; } return type === 'array' || type !== 'function' && type !== 'string' && (length === 0 || typeof length === 'number' && length > 0 && (length - 1) in obj); } function Widget( uploader ) { this.owner = uploader; this.options = uploader.options; } $.extend( Widget.prototype, { init: Base.noop, // 绫籅ackbone鐨勪簨浠剁洃鍚0鏄庯紝鐩戝惉uploader瀹炰緥涓婄殑浜嬩欢 // widget鐩存帴鏃犳硶鐩戝惉浜嬩欢锛屼簨浠跺彧鑳介€氳繃uploader鏉ヤ紶閫 invoke: function( apiName, args ) { /* { 'make-thumb': 'makeThumb' } */ var map = this.responseMap; // 濡傛灉鏃燗PI鍝嶅簲澹版槑鍒欏拷鐣 if ( !map || !(apiName in map) || !(map[ apiName ] in this) || !$.isFunction( this[ map[ apiName ] ] ) ) { return IGNORE; } return this[ map[ apiName ] ].apply( this, args ); }, /** * 鍙戦€佸懡浠ゃ€傚綋浼犲叆`callback`鎴栬€卄handler`涓繑鍥瀈promise`鏃躲€傝繑鍥炰竴涓綋鎵€鏈塦handler`涓殑promise閮藉畬鎴愬悗瀹屾垚鐨勬柊`promise`銆 * @method request * @grammar request( command, args ) => * | Promise * @grammar request( command, args, callback ) => Promise * @for Uploader */ request: function() { return this.owner.request.apply( this.owner, arguments ); } }); // 鎵╁睍Uploader. $.extend( Uploader.prototype, { /** * @property {String | Array} [disableWidgets=undefined] * @namespace options * @for Uploader * @description 榛樿鎵€鏈 Uploader.register 浜嗙殑 widget 閮戒細琚姞杞斤紝濡傛灉绂佺敤鏌愪竴閮ㄥ垎锛岃閫氳繃姝 option 鎸囧畾榛戝悕鍗曘€ */ // 瑕嗗啓_init鐢ㄦ潵鍒濆鍖杦idgets _init: function() { var me = this, widgets = me._widgets = [], deactives = me.options.disableWidgets || ''; $.each( widgetClass, function( _, klass ) { (!deactives || !~deactives.indexOf( klass._name )) && widgets.push( new klass( me ) ); }); return _init.apply( me, arguments ); }, request: function( apiName, args, callback ) { var i = 0, widgets = this._widgets, len = widgets && widgets.length, rlts = [], dfds = [], widget, rlt, promise, key; args = isArrayLike( args ) ? args : [ args ]; for ( ; i < len; i++ ) { widget = widgets[ i ]; rlt = widget.invoke( apiName, args ); if ( rlt !== IGNORE ) { // Deferred瀵硅薄 if ( Base.isPromise( rlt ) ) { dfds.push( rlt ); } else { rlts.push( rlt ); } } } // 濡傛灉鏈塩allback锛屽垯鐢ㄥ紓姝ユ柟寮忋€ if ( callback || dfds.length ) { promise = Base.when.apply( Base, dfds ); key = promise.pipe ? 'pipe' : 'then'; // 寰堥噸瑕佷笉鑳藉垹闄ゃ€傚垹闄や簡浼氭寰幆銆 // 淇濊瘉鎵ц椤哄簭銆傝callback鎬绘槸鍦ㄤ笅涓€涓 tick 涓墽琛屻€ return promise[ key ](function() { var deferred = Base.Deferred(), args = arguments; if ( args.length === 1 ) { args = args[ 0 ]; } setTimeout(function() { deferred.resolve( args ); }, 1 ); return deferred.promise(); })[ callback ? key : 'done' ]( callback || Base.noop ); } else { return rlts[ 0 ]; } }, destroy: function() { _destroy.apply( this, arguments ); this._widgets = null; } }); /** * 娣诲姞缁勪欢 * @grammar Uploader.register(proto); * @grammar Uploader.register(map, proto); * @param {object} responseMap API 鍚嶇О涓庡嚱鏁板疄鐜扮殑鏄犲皠 * @param {object} proto 缁勪欢鍘熷瀷锛屾瀯閫犲嚱鏁伴€氳繃 constructor 灞炴€у畾涔 * @method Uploader.register * @for Uploader * @example * Uploader.register({ * 'make-thumb': 'makeThumb' * }, { * init: function( options ) {}, * makeThumb: function() {} * }); * * Uploader.register({ * 'make-thumb': function() { * * } * }); */ Uploader.register = Widget.register = function( responseMap, widgetProto ) { var map = { init: 'init', destroy: 'destroy', name: 'anonymous' }, klass; if ( arguments.length === 1 ) { widgetProto = responseMap; // 鑷姩鐢熸垚 map 琛ㄣ€ $.each(widgetProto, function(key) { if ( key[0] === '_' || key === 'name' ) { key === 'name' && (map.name = widgetProto.name); return; } map[key.replace(/[A-Z]/g, '-$&').toLowerCase()] = key; }); } else { map = $.extend( map, responseMap ); } widgetProto.responseMap = map; klass = Base.inherits( Widget, widgetProto ); klass._name = map.name; widgetClass.push( klass ); return klass; }; /** * 鍒犻櫎鎻掍欢锛屽彧鏈夊湪娉ㄥ唽鏃舵寚瀹氫簡鍚嶅瓧鐨勬墠鑳借鍒犻櫎銆 * @grammar Uploader.unRegister(name); * @param {string} name 缁勪欢鍚嶅瓧 * @method Uploader.unRegister * @for Uploader * @example * * Uploader.register({ * name: 'custom', * * 'make-thumb': function() { * * } * }); * * Uploader.unRegister('custom'); */ Uploader.unRegister = Widget.unRegister = function( name ) { if ( !name || name === 'anonymous' ) { return; } // 鍒犻櫎鎸囧畾鐨勬彃浠躲€ for ( var i = widgetClass.length; i--; ) { if ( widgetClass[i]._name === name ) { widgetClass.splice(i, 1) } } }; return Widget; }); /** * @fileOverview DragAndDrop Widget銆 */ define('widgets/filednd',[ 'base', 'uploader', 'lib/dnd', 'widgets/widget' ], function( Base, Uploader, Dnd ) { var $ = Base.$; Uploader.options.dnd = ''; /** * @property {Selector} [dnd=undefined] 鎸囧畾Drag And Drop鎷栨嫿鐨勫鍣紝濡傛灉涓嶆寚瀹氾紝鍒欎笉鍚姩銆 * @namespace options * @for Uploader */ /** * @property {Selector} [disableGlobalDnd=false] 鏄惁绂佹帀鏁翠釜椤甸潰鐨勬嫋鎷藉姛鑳斤紝濡傛灉涓嶇鐢紝鍥剧墖鎷栬繘鏉ョ殑鏃跺€欎細榛樿琚祻瑙堝櫒鎵撳紑銆 * @namespace options * @for Uploader */ /** * @event dndAccept * @param {DataTransferItemList} items DataTransferItem * @description 闃绘姝や簨浠跺彲浠ユ嫆缁濇煇浜涚被鍨嬬殑鏂囦欢鎷栧叆杩涙潵銆傜洰鍓嶅彧鏈 chrome 鎻愪緵杩欐牱鐨 API锛屼笖鍙兘閫氳繃 mime-type 楠岃瘉銆 * @for Uploader */ return Uploader.register({ name: 'dnd', init: function( opts ) { if ( !opts.dnd || this.request('predict-runtime-type') !== 'html5' ) { return; } var me = this, deferred = Base.Deferred(), options = $.extend({}, { disableGlobalDnd: opts.disableGlobalDnd, container: opts.dnd, accept: opts.accept }), dnd; this.dnd = dnd = new Dnd( options ); dnd.once( 'ready', deferred.resolve ); dnd.on( 'drop', function( files ) { me.request( 'add-file', [ files ]); }); // 妫€娴嬫枃浠舵槸鍚﹀叏閮ㄥ厑璁告坊鍔犮€ dnd.on( 'accept', function( items ) { return me.owner.trigger( 'dndAccept', items ); }); dnd.init(); return deferred.promise(); }, destroy: function() { this.dnd && this.dnd.destroy(); } }); }); /** * @fileOverview 閿欒淇℃伅 */ define('lib/filepaste',[ 'base', 'mediator', 'runtime/client' ], function( Base, Mediator, RuntimeClent ) { var $ = Base.$; function FilePaste( opts ) { opts = this.options = $.extend({}, opts ); opts.container = $( opts.container || document.body ); RuntimeClent.call( this, 'FilePaste' ); } Base.inherits( RuntimeClent, { constructor: FilePaste, init: function() { var me = this; me.connectRuntime( me.options, function() { me.exec('init'); me.trigger('ready'); }); } }); Mediator.installTo( FilePaste.prototype ); return FilePaste; }); /** * @fileOverview 缁勪欢鍩虹被銆 */ define('widgets/filepaste',[ 'base', 'uploader', 'lib/filepaste', 'widgets/widget' ], function( Base, Uploader, FilePaste ) { var $ = Base.$; /** * @property {Selector} [paste=undefined] 鎸囧畾鐩戝惉paste浜嬩欢鐨勫鍣紝濡傛灉涓嶆寚瀹氾紝涓嶅惎鐢ㄦ鍔熻兘銆傛鍔熻兘涓洪€氳繃绮樿创鏉ユ坊鍔犳埅灞忕殑鍥剧墖銆傚缓璁缃负`document.body`. * @namespace options * @for Uploader */ return Uploader.register({ name: 'paste', init: function( opts ) { if ( !opts.paste || this.request('predict-runtime-type') !== 'html5' ) { return; } var me = this, deferred = Base.Deferred(), options = $.extend({}, { container: opts.paste, accept: opts.accept }), paste; this.paste = paste = new FilePaste( options ); paste.once( 'ready', deferred.resolve ); paste.on( 'paste', function( files ) { me.owner.request( 'add-file', [ files ]); }); paste.init(); return deferred.promise(); }, destroy: function() { this.paste && this.paste.destroy(); } }); }); /** * @fileOverview Blob */ define('lib/blob',[ 'base', 'runtime/client' ], function( Base, RuntimeClient ) { function Blob( ruid, source ) { var me = this; me.source = source; me.ruid = ruid; this.size = source.size || 0; // 濡傛灉娌℃湁鎸囧畾 mimetype, 浣嗘槸鐭ラ亾鏂囦欢鍚庣紑銆 if ( !source.type && this.ext && ~'jpg,jpeg,png,gif,bmp'.indexOf( this.ext ) ) { this.type = 'image/' + (this.ext === 'jpg' ? 'jpeg' : this.ext); } else { this.type = source.type || 'application/octet-stream'; } RuntimeClient.call( me, 'Blob' ); this.uid = source.uid || this.uid; if ( ruid ) { me.connectRuntime( ruid ); } } Base.inherits( RuntimeClient, { constructor: Blob, slice: function( start, end ) { return this.exec( 'slice', start, end ); }, getSource: function() { return this.source; } }); return Blob; }); /** * 涓轰簡缁熶竴鍖朏lash鐨凢ile鍜孒TML5鐨凢ile鑰屽瓨鍦ㄣ€ * 浠ヨ嚦浜庤璋冪敤Flash閲岄潰鐨凢ile锛屼篃鍙互鍍忚皟鐢℉TML5鐗堟湰鐨凢ile涓€涓嬨€ * @fileOverview File */ define('lib/file',[ 'base', 'lib/blob' ], function( Base, Blob ) { var uid = 1, rExt = /\.([^.]+)$/; function File( ruid, file ) { var ext; this.name = file.name || ('untitled' + uid++); ext = rExt.exec( file.name ) ? RegExp.$1.toLowerCase() : ''; // todo 鏀寔鍏朵粬绫诲瀷鏂囦欢鐨勮浆鎹€ // 濡傛灉鏈 mimetype, 浣嗘槸鏂囦欢鍚嶉噷闈㈡病鏈夋壘鍑哄悗缂€瑙勫緥 if ( !ext && file.type ) { ext = /\/(jpg|jpeg|png|gif|bmp)$/i.exec( file.type ) ? RegExp.$1.toLowerCase() : ''; this.name += '.' + ext; } this.ext = ext; this.lastModifiedDate = file.lastModifiedDate || (new Date()).toLocaleString(); Blob.apply( this, arguments ); } return Base.inherits( Blob, File ); }); /** * @fileOverview 閿欒淇℃伅 */ define('lib/filepicker',[ 'base', 'runtime/client', 'lib/file' ], function( Base, RuntimeClent, File ) { var $ = Base.$; function FilePicker( opts ) { opts = this.options = $.extend({}, FilePicker.options, opts ); opts.container = $( opts.id ); if ( !opts.container.length ) { throw new Error('鎸夐挳鎸囧畾閿欒'); } opts.innerHTML = opts.innerHTML || opts.label || opts.container.html() || ''; opts.button = $( opts.button || document.createElement('div') ); opts.button.html( opts.innerHTML ); opts.container.html( opts.button ); RuntimeClent.call( this, 'FilePicker', true ); } FilePicker.options = { button: null, container: null, label: null, innerHTML: null, multiple: true, accept: null, name: 'file' }; Base.inherits( RuntimeClent, { constructor: FilePicker, init: function() { var me = this, opts = me.options, button = opts.button; button.addClass('webuploader-pick'); me.on( 'all', function( type ) { var files; switch ( type ) { case 'mouseenter': button.addClass('webuploader-pick-hover'); break; case 'mouseleave': button.removeClass('webuploader-pick-hover'); break; case 'change': files = me.exec('getFiles'); me.trigger( 'select', $.map( files, function( file ) { file = new File( me.getRuid(), file ); // 璁板綍鏉ユ簮銆 file._refer = opts.container; return file; }), opts.container ); break; } }); me.connectRuntime( opts, function() { me.refresh(); me.exec( 'init', opts ); me.trigger('ready'); }); this._resizeHandler = Base.bindFn( this.refresh, this ); $( window ).on( 'resize', this._resizeHandler ); }, refresh: function() { var shimContainer = this.getRuntime().getContainer(), button = this.options.button, width = button.outerWidth ? button.outerWidth() : button.width(), height = button.outerHeight ? button.outerHeight() : button.height(), pos = button.offset(); width && height && shimContainer.css({ bottom: 'auto', right: 'auto', width: width + 'px', height: height + 'px' }).offset( pos ); }, enable: function() { var btn = this.options.button; btn.removeClass('webuploader-pick-disable'); this.refresh(); }, disable: function() { var btn = this.options.button; this.getRuntime().getContainer().css({ top: '-99999px' }); btn.addClass('webuploader-pick-disable'); }, destroy: function() { var btn = this.options.button; $( window ).off( 'resize', this._resizeHandler ); btn.removeClass('webuploader-pick-disable webuploader-pick-hover ' + 'webuploader-pick'); } }); return FilePicker; }); /** * @fileOverview 鏂囦欢閫夋嫨鐩稿叧 */ define('widgets/filepicker',[ 'base', 'uploader', 'lib/filepicker', 'widgets/widget' ], function( Base, Uploader, FilePicker ) { var $ = Base.$; $.extend( Uploader.options, { /** * @property {Selector | Object} [pick=undefined] * @namespace options * @for Uploader * @description 鎸囧畾閫夋嫨鏂囦欢鐨勬寜閽鍣紝涓嶆寚瀹氬垯涓嶅垱寤烘寜閽€ * * * `id` {Seletor|dom} 鎸囧畾閫夋嫨鏂囦欢鐨勬寜閽鍣紝涓嶆寚瀹氬垯涓嶅垱寤烘寜閽€?*娉ㄦ剰** 杩欓噷铏界劧鍐欑殑鏄 id, 浣嗘槸涓嶆槸鍙敮鎸 id, 杩樻敮鎸 class, 鎴栬€ dom 鑺傜偣銆 * * `label` {String} 璇烽噰鐢 `innerHTML` 浠f浛 * * `innerHTML` {String} 鎸囧畾鎸夐挳鏂囧瓧銆備笉鎸囧畾鏃朵紭鍏堜粠鎸囧畾鐨勫鍣ㄤ腑鐪嬫槸鍚﹁嚜甯︽枃瀛椼€ * * `multiple` {Boolean} 鏄惁寮€璧峰悓鏃堕€夋嫨澶氫釜鏂囦欢鑳藉姏銆 */ pick: null, /** * @property {Arroy} [accept=null] * @namespace options * @for Uploader * @description 鎸囧畾鎺ュ彈鍝簺绫诲瀷鐨勬枃浠躲€ 鐢变簬鐩墠杩樻湁ext杞琺imeType琛紝鎵€浠ヨ繖閲岄渶瑕佸垎寮€鎸囧畾銆 * * * `title` {String} 鏂囧瓧鎻忚堪 * * `extensions` {String} 鍏佽鐨勬枃浠跺悗缂€锛屼笉甯︾偣锛屽涓敤閫楀彿鍒嗗壊銆 * * `mimeTypes` {String} 澶氫釜鐢ㄩ€楀彿鍒嗗壊銆 * * 濡傦細 * * ``` * { * title: 'Images', * extensions: 'gif,jpg,jpeg,bmp,png', * mimeTypes: 'image/*' * } * ``` */ accept: null/*{ title: 'Images', extensions: 'gif,jpg,jpeg,bmp,png', mimeTypes: 'image/*' }*/ }); return Uploader.register({ name: 'picker', init: function( opts ) { this.pickers = []; return opts.pick && this.addBtn( opts.pick ); }, refresh: function() { $.each( this.pickers, function() { this.refresh(); }); }, /** * @method addButton * @for Uploader * @grammar addButton( pick ) => Promise * @description * 娣诲姞鏂囦欢閫夋嫨鎸夐挳锛屽鏋滀竴涓寜閽笉澶燂紝闇€瑕佽皟鐢ㄦ鏂规硶鏉ユ坊鍔犮€傚弬鏁拌窡[options.pick](#WebUploader:Uploader:options)涓€鑷淬€ * @example * uploader.addButton({ * id: '#btnContainer', * innerHTML: '閫夋嫨鏂囦欢' * }); */ addBtn: function( pick ) { var me = this, opts = me.options, accept = opts.accept, promises = []; if ( !pick ) { return; } $.isPlainObject( pick ) || (pick = { id: pick }); $( pick.id ).each(function() { var options, picker, deferred; deferred = Base.Deferred(); options = $.extend({}, pick, { accept: $.isPlainObject( accept ) ? [ accept ] : accept, swf: opts.swf, runtimeOrder: opts.runtimeOrder, id: this }); picker = new FilePicker( options ); picker.once( 'ready', deferred.resolve ); picker.on( 'select', function( files ) { me.owner.request( 'add-file', [ files ]); }); picker.init(); me.pickers.push( picker ); promises.push( deferred.promise() ); }); return Base.when.apply( Base, promises ); }, disable: function() { $.each( this.pickers, function() { this.disable(); }); }, enable: function() { $.each( this.pickers, function() { this.enable(); }); }, destroy: function() { $.each( this.pickers, function() { this.destroy(); }); this.pickers = null; } }); }); /** * @fileOverview Image */ define('lib/image',[ 'base', 'runtime/client', 'lib/blob' ], function( Base, RuntimeClient, Blob ) { var $ = Base.$; // 鏋勯€犲櫒銆 function Image( opts ) { this.options = $.extend({}, Image.options, opts ); RuntimeClient.call( this, 'Image' ); this.on( 'load', function() { this._info = this.exec('info'); this._meta = this.exec('meta'); }); } // 榛樿閫夐」銆 Image.options = { // 榛樿鐨勫浘鐗囧鐞嗚川閲 quality: 90, // 鏄惁瑁佸壀 crop: false, // 鏄惁淇濈暀澶撮儴淇℃伅 preserveHeaders: false, // 鏄惁鍏佽鏀惧ぇ銆 allowMagnify: false }; // 缁ф壙RuntimeClient. Base.inherits( RuntimeClient, { constructor: Image, info: function( val ) { // setter if ( val ) { this._info = val; return this; } // getter return this._info; }, meta: function( val ) { // setter if ( val ) { this._meta = val; return this; } // getter return this._meta; }, loadFromBlob: function( blob ) { var me = this, ruid = blob.getRuid(); this.connectRuntime( ruid, function() { me.exec( 'init', me.options ); me.exec( 'loadFromBlob', blob ); }); }, resize: function() { var args = Base.slice( arguments ); return this.exec.apply( this, [ 'resize' ].concat( args ) ); }, crop: function() { var args = Base.slice( arguments ); return this.exec.apply( this, [ 'crop' ].concat( args ) ); }, getAsDataUrl: function( type ) { return this.exec( 'getAsDataUrl', type ); }, getAsBlob: function( type ) { var blob = this.exec( 'getAsBlob', type ); return new Blob( this.getRuid(), blob ); } }); return Image; }); /** * @fileOverview 鍥剧墖鎿嶄綔, 璐熻矗棰勮鍥剧墖鍜屼笂浼犲墠鍘嬬缉鍥剧墖 */ define('widgets/image',[ 'base', 'uploader', 'lib/image', 'widgets/widget' ], function( Base, Uploader, Image ) { var $ = Base.$, throttle; // 鏍规嵁瑕佸鐞嗙殑鏂囦欢澶у皬鏉ヨ妭娴侊紝涓€娆′笉鑳藉鐞嗗お澶氾紝浼氬崱銆 throttle = (function( max ) { var occupied = 0, waiting = [], tick = function() { var item; while ( waiting.length && occupied < max ) { item = waiting.shift(); occupied += item[ 0 ]; item[ 1 ](); } }; return function( emiter, size, cb ) { waiting.push([ size, cb ]); emiter.once( 'destroy', function() { occupied -= size; setTimeout( tick, 1 ); }); setTimeout( tick, 1 ); }; })( 5 * 1024 * 1024 ); $.extend( Uploader.options, { /** * @property {Object} [thumb] * @namespace options * @for Uploader * @description 閰嶇疆鐢熸垚缂╃暐鍥剧殑閫夐」銆 * * 榛樿涓猴細 * * ```javascript * { * width: 110, * height: 110, * * // 鍥剧墖璐ㄩ噺锛屽彧鏈塼ype涓篳image/jpeg`鐨勬椂鍊欐墠鏈夋晥銆 * quality: 70, * * // 鏄惁鍏佽鏀惧ぇ锛屽鏋滄兂瑕佺敓鎴愬皬鍥剧殑鏃跺€欎笉澶辩湡锛屾閫夐」搴旇璁剧疆涓篺alse. * allowMagnify: true, * * // 鏄惁鍏佽瑁佸壀銆 * crop: true, * * // 涓虹┖鐨勮瘽鍒欎繚鐣欏師鏈夊浘鐗囨牸寮忋€ * // 鍚﹀垯寮哄埗杞崲鎴愭寚瀹氱殑绫诲瀷銆 * type: 'image/jpeg' * } * ``` */ thumb: { width: 110, height: 110, quality: 70, allowMagnify: true, crop: true, preserveHeaders: false, // 涓虹┖鐨勮瘽鍒欎繚鐣欏師鏈夊浘鐗囨牸寮忋€ // 鍚﹀垯寮哄埗杞崲鎴愭寚瀹氱殑绫诲瀷銆 // IE 8涓嬮潰 base64 澶у皬涓嶈兘瓒呰繃 32K 鍚﹀垯棰勮澶辫触锛岃€岄潪 jpeg 缂栫爜鐨勫浘鐗囧緢鍙 // 鑳戒細瓒呰繃 32k, 鎵€浠ヨ繖閲岃缃垚棰勮鐨勬椂鍊欓兘鏄 image/jpeg type: 'image/jpeg' }, /** * @property {Object} [compress] * @namespace options * @for Uploader * @description 閰嶇疆鍘嬬缉鐨勫浘鐗囩殑閫夐」銆傚鏋滄閫夐」涓篳false`, 鍒欏浘鐗囧湪涓婁紶鍓嶄笉杩涜鍘嬬缉銆 * * 榛樿涓猴細 * * ```javascript * { * width: 1600, * height: 1600, * * // 鍥剧墖璐ㄩ噺锛屽彧鏈塼ype涓篳image/jpeg`鐨勬椂鍊欐墠鏈夋晥銆 * quality: 90, * * // 鏄惁鍏佽鏀惧ぇ锛屽鏋滄兂瑕佺敓鎴愬皬鍥剧殑鏃跺€欎笉澶辩湡锛屾閫夐」搴旇璁剧疆涓篺alse. * allowMagnify: false, * * // 鏄惁鍏佽瑁佸壀銆 * crop: false, * * // 鏄惁淇濈暀澶撮儴meta淇℃伅銆 * preserveHeaders: true, * * // 濡傛灉鍙戠幇鍘嬬缉鍚庢枃浠跺ぇ灏忔瘮鍘熸潵杩樺ぇ锛屽垯浣跨敤鍘熸潵鍥剧墖 * // 姝ゅ睘鎬у彲鑳戒細褰卞搷鍥剧墖鑷姩绾犳鍔熻兘 * noCompressIfLarger: false, * * // 鍗曚綅瀛楄妭锛屽鏋滃浘鐗囧ぇ灏忓皬浜庢鍊硷紝涓嶄細閲囩敤鍘嬬缉銆 * compressSize: 0 * } * ``` */ compress: { quality: 90, allowMagnify: false, crop: false, preserveHeaders: true } }); return Uploader.register({ name: 'image', /** * 鐢熸垚缂╃暐鍥撅紝姝よ繃绋嬩负寮傛锛屾墍浠ラ渶瑕佷紶鍏callback`銆 * 閫氬父鎯呭喌鍦ㄥ浘鐗囧姞鍏ラ槦閲屽悗璋冪敤姝ゆ柟娉曟潵鐢熸垚棰勮鍥句互澧炲己浜や簰鏁堟灉銆 * * 褰 width 鎴栬€ height 鐨勫€间粙浜 0 - 1 鏃讹紝琚綋鎴愮櫨鍒嗘瘮浣跨敤銆 * * `callback`涓彲浠ユ帴鏀跺埌涓や釜鍙傛暟銆 * * 绗竴涓负error锛屽鏋滅敓鎴愮缉鐣ュ浘鏈夐敊璇紝姝rror灏嗕负鐪熴€ * * 绗簩涓负ret, 缂╃暐鍥剧殑Data URL鍊笺€ * * **娉ㄦ剰** * Date URL鍦↖E6/7涓笉鏀寔锛屾墍浠ヤ笉鐢ㄨ皟鐢ㄦ鏂规硶浜嗭紝鐩存帴鏄剧ず涓€寮犳殏涓嶆敮鎸侀瑙堝浘鐗囧ソ浜嗐€ * 涔熷彲浠ュ€熷姪鏈嶅姟绔紝灏 base64 鏁版嵁浼犵粰鏈嶅姟绔紝鐢熸垚涓€涓复鏃舵枃浠朵緵棰勮銆 * * @method makeThumb * @grammar makeThumb( file, callback ) => undefined * @grammar makeThumb( file, callback, width, height ) => undefined * @for Uploader * @example * * uploader.on( 'fileQueued', function( file ) { * var $li = ...; * * uploader.makeThumb( file, function( error, ret ) { * if ( error ) { * $li.text('棰勮閿欒'); * } else { * $li.append(''); * } * }); * * }); */ makeThumb: function( file, cb, width, height ) { var opts, image; file = this.request( 'get-file', file ); // 鍙瑙堝浘鐗囨牸寮忋€ if ( !file.type.match( /^image/ ) ) { cb( true ); return; } opts = $.extend({}, this.options.thumb ); // 濡傛灉浼犲叆鐨勬槸object. if ( $.isPlainObject( width ) ) { opts = $.extend( opts, width ); width = null; } width = width || opts.width; height = height || opts.height; image = new Image( opts ); image.once( 'load', function() { file._info = file._info || image.info(); file._meta = file._meta || image.meta(); // 濡傛灉 width 鐨勫€间粙浜 0 - 1 // 璇存槑璁剧疆鐨勬槸鐧惧垎姣斻€ if ( width <= 1 && width > 0 ) { width = file._info.width * width; } // 鍚屾牱鐨勮鍒欏簲鐢ㄤ簬 height if ( height <= 1 && height > 0 ) { height = file._info.height * height; } image.resize( width, height ); }); // 褰 resize 瀹屽悗 image.once( 'complete', function() { cb( false, image.getAsDataUrl( opts.type ) ); image.destroy(); }); image.once( 'error', function( reason ) { cb( reason || true ); image.destroy(); }); throttle( image, file.source.size, function() { file._info && image.info( file._info ); file._meta && image.meta( file._meta ); image.loadFromBlob( file.source ); }); }, beforeSendFile: function( file ) { var opts = this.options.compress || this.options.resize, compressSize = opts && opts.compressSize || 0, noCompressIfLarger = opts && opts.noCompressIfLarger || false, image, deferred; file = this.request( 'get-file', file ); // 鍙帇缂 jpeg 鍥剧墖鏍煎紡銆 // gif 鍙兘浼氫涪澶遍拡 // bmp png 鍩烘湰涓婂昂瀵搁兘涓嶅ぇ锛屼笖鍘嬬缉姣旀瘮杈冨皬銆 if ( !opts || !~'image/jpeg,image/jpg'.indexOf( file.type ) || file.size < compressSize || file._compressed ) { return; } opts = $.extend({}, opts ); deferred = Base.Deferred(); image = new Image( opts ); deferred.always(function() { image.destroy(); image = null; }); image.once( 'error', deferred.reject ); image.once( 'load', function() { var width = opts.width, height = opts.height; file._info = file._info || image.info(); file._meta = file._meta || image.meta(); // 濡傛灉 width 鐨勫€间粙浜 0 - 1 // 璇存槑璁剧疆鐨勬槸鐧惧垎姣斻€ if ( width <= 1 && width > 0 ) { width = file._info.width * width; } // 鍚屾牱鐨勮鍒欏簲鐢ㄤ簬 height if ( height <= 1 && height > 0 ) { height = file._info.height * height; } image.resize( width, height ); }); image.once( 'complete', function() { var blob, size; // 绉诲姩绔 UC / qq 娴忚鍣ㄧ殑鏃犲浘妯″紡涓 // ctx.getImageData 澶勭悊澶у浘鐨勬椂鍊欎細鎶 Exception // INDEX_SIZE_ERR: DOM Exception 1 try { blob = image.getAsBlob( opts.type ); size = file.size; // 濡傛灉鍘嬬缉鍚庯紝姣斿師鏉ヨ繕澶у垯涓嶇敤鍘嬬缉鍚庣殑銆 if ( !noCompressIfLarger || blob.size < size ) { // file.source.destroy && file.source.destroy(); file.source = blob; file.size = blob.size; file.trigger( 'resize', blob.size, size ); } // 鏍囪锛岄伩鍏嶉噸澶嶅帇缂┿€ file._compressed = true; deferred.resolve(); } catch ( e ) { // 鍑洪敊浜嗙洿鎺ョ户缁紝璁╁叾涓婁紶鍘熷鍥剧墖 deferred.resolve(); } }); file._info && image.info( file._info ); file._meta && image.meta( file._meta ); image.loadFromBlob( file.source ); return deferred.promise(); } }); }); /** * @fileOverview 鏂囦欢灞炴€у皝瑁 */ define('file',[ 'base', 'mediator' ], function( Base, Mediator ) { var $ = Base.$, idPrefix = 'WU_FILE_', idSuffix = 0, rExt = /\.([^.]+)$/, statusMap = {}; function gid() { return idPrefix + idSuffix++; } /** * 鏂囦欢绫 * @class File * @constructor 鏋勯€犲嚱鏁 * @grammar new File( source ) => File * @param {Lib.File} source [lib.File](#Lib.File)瀹炰緥, 姝ource瀵硅薄鏄甫鏈塕untime淇℃伅鐨勩€ */ function WUFile( source ) { /** * 鏂囦欢鍚嶏紝鍖呮嫭鎵╁睍鍚嶏紙鍚庣紑锛 * @property name * @type {string} */ this.name = source.name || 'Untitled'; /** * 鏂囦欢浣撶Н锛堝瓧鑺傦級 * @property size * @type {uint} * @default 0 */ this.size = source.size || 0; /** * 鏂囦欢MIMETYPE绫诲瀷锛屼笌鏂囦欢绫诲瀷鐨勫搴斿叧绯昏鍙傝€僛http://t.cn/z8ZnFny](http://t.cn/z8ZnFny) * @property type * @type {string} * @default 'application/octet-stream' */ this.type = source.type || 'application/octet-stream'; /** * 鏂囦欢鏈€鍚庝慨鏀规棩鏈 * @property lastModifiedDate * @type {int} * @default 褰撳墠鏃堕棿鎴 */ this.lastModifiedDate = source.lastModifiedDate || (new Date() * 1); /** * 鏂囦欢ID锛屾瘡涓璞″叿鏈夊敮涓€ID锛屼笌鏂囦欢鍚嶆棤鍏 * @property id * @type {string} */ this.id = gid(); /** * 鏂囦欢鎵╁睍鍚嶏紝閫氳繃鏂囦欢鍚嶈幏鍙栵紝渚嬪test.png鐨勬墿灞曞悕涓簆ng * @property ext * @type {string} */ this.ext = rExt.exec( this.name ) ? RegExp.$1 : ''; /** * 鐘舵€佹枃瀛楄鏄庛€傚湪涓嶅悓鐨剆tatus璇涓嬫湁涓嶅悓鐨勭敤閫斻€ * @property statusText * @type {string} */ this.statusText = ''; // 瀛樺偍鏂囦欢鐘舵€侊紝闃叉閫氳繃灞炴€х洿鎺ヤ慨鏀 statusMap[ this.id ] = WUFile.Status.INITED; this.source = source; this.loaded = 0; this.on( 'error', function( msg ) { this.setStatus( WUFile.Status.ERROR, msg ); }); } $.extend( WUFile.prototype, { /** * 璁剧疆鐘舵€侊紝鐘舵€佸彉鍖栨椂浼氳Е鍙慲change`浜嬩欢銆 * @method setStatus * @grammar setStatus( status[, statusText] ); * @param {File.Status|String} status [鏂囦欢鐘舵€佸€糫(#WebUploader:File:File.Status) * @param {String} [statusText=''] 鐘舵€佽鏄庯紝甯稿湪error鏃朵娇鐢紝鐢╤ttp, abort,server绛夋潵鏍囪鏄敱浜庝粈涔堝師鍥犲鑷存枃浠堕敊璇€ */ setStatus: function( status, text ) { var prevStatus = statusMap[ this.id ]; typeof text !== 'undefined' && (this.statusText = text); if ( status !== prevStatus ) { statusMap[ this.id ] = status; /** * 鏂囦欢鐘舵€佸彉鍖 * @event statuschange */ this.trigger( 'statuschange', status, prevStatus ); } }, /** * 鑾峰彇鏂囦欢鐘舵€ * @return {File.Status} * @example 鏂囦欢鐘舵€佸叿浣撳寘鎷互涓嬪嚑绉嶇被鍨嬶細 { // 鍒濆鍖 INITED: 0, // 宸插叆闃熷垪 QUEUED: 1, // 姝e湪涓婁紶 PROGRESS: 2, // 涓婁紶鍑洪敊 ERROR: 3, // 涓婁紶鎴愬姛 COMPLETE: 4, // 涓婁紶鍙栨秷 CANCELLED: 5 } */ getStatus: function() { return statusMap[ this.id ]; }, /** * 鑾峰彇鏂囦欢鍘熷淇℃伅銆 * @return {*} */ getSource: function() { return this.source; }, destroy: function() { this.off(); delete statusMap[ this.id ]; } }); Mediator.installTo( WUFile.prototype ); /** * 鏂囦欢鐘舵€佸€硷紝鍏蜂綋鍖呮嫭浠ヤ笅鍑犵绫诲瀷锛 * * `inited` 鍒濆鐘舵€ * * `queued` 宸茬粡杩涘叆闃熷垪, 绛夊緟涓婁紶 * * `progress` 涓婁紶涓 * * `complete` 涓婁紶瀹屾垚銆 * * `error` 涓婁紶鍑洪敊锛屽彲閲嶈瘯 * * `interrupt` 涓婁紶涓柇锛屽彲缁紶銆 * * `invalid` 鏂囦欢涓嶅悎鏍硷紝涓嶈兘閲嶈瘯涓婁紶銆備細鑷姩浠庨槦鍒椾腑绉婚櫎銆 * * `cancelled` 鏂囦欢琚Щ闄ゃ€ * @property {Object} Status * @namespace File * @class File * @static */ WUFile.Status = { INITED: 'inited', // 鍒濆鐘舵€ QUEUED: 'queued', // 宸茬粡杩涘叆闃熷垪, 绛夊緟涓婁紶 PROGRESS: 'progress', // 涓婁紶涓 ERROR: 'error', // 涓婁紶鍑洪敊锛屽彲閲嶈瘯 COMPLETE: 'complete', // 涓婁紶瀹屾垚銆 CANCELLED: 'cancelled', // 涓婁紶鍙栨秷銆 INTERRUPT: 'interrupt', // 涓婁紶涓柇锛屽彲缁紶銆 INVALID: 'invalid' // 鏂囦欢涓嶅悎鏍硷紝涓嶈兘閲嶈瘯涓婁紶銆 }; return WUFile; }); /** * @fileOverview 鏂囦欢闃熷垪 */ define('queue',[ 'base', 'mediator', 'file' ], function( Base, Mediator, WUFile ) { var $ = Base.$, STATUS = WUFile.Status; /** * 鏂囦欢闃熷垪, 鐢ㄦ潵瀛樺偍鍚勪釜鐘舵€佷腑鐨勬枃浠躲€ * @class Queue * @extends Mediator */ function Queue() { /** * 缁熻鏂囦欢鏁般€ * * `numOfQueue` 闃熷垪涓殑鏂囦欢鏁般€ * * `numOfSuccess` 涓婁紶鎴愬姛鐨勬枃浠舵暟 * * `numOfCancel` 琚彇娑堢殑鏂囦欢鏁 * * `numOfProgress` 姝e湪涓婁紶涓殑鏂囦欢鏁 * * `numOfUploadFailed` 涓婁紶閿欒鐨勬枃浠舵暟銆 * * `numOfInvalid` 鏃犳晥鐨勬枃浠舵暟銆 * * `numofDeleted` 琚Щ闄ょ殑鏂囦欢鏁般€ * @property {Object} stats */ this.stats = { numOfQueue: 0, numOfSuccess: 0, numOfCancel: 0, numOfProgress: 0, numOfUploadFailed: 0, numOfInvalid: 0, numofDeleted: 0, numofInterrupt: 0 }; // 涓婁紶闃熷垪锛屼粎鍖呮嫭绛夊緟涓婁紶鐨勬枃浠 this._queue = []; // 瀛樺偍鎵€鏈夋枃浠 this._map = {}; } $.extend( Queue.prototype, { /** * 灏嗘柊鏂囦欢鍔犲叆瀵归槦鍒楀熬閮 * * @method append * @param {File} file 鏂囦欢瀵硅薄 */ append: function( file ) { this._queue.push( file ); this._fileAdded( file ); return this; }, /** * 灏嗘柊鏂囦欢鍔犲叆瀵归槦鍒楀ご閮 * * @method prepend * @param {File} file 鏂囦欢瀵硅薄 */ prepend: function( file ) { this._queue.unshift( file ); this._fileAdded( file ); return this; }, /** * 鑾峰彇鏂囦欢瀵硅薄 * * @method getFile * @param {String} fileId 鏂囦欢ID * @return {File} */ getFile: function( fileId ) { if ( typeof fileId !== 'string' ) { return fileId; } return this._map[ fileId ]; }, /** * 浠庨槦鍒椾腑鍙栧嚭涓€涓寚瀹氱姸鎬佺殑鏂囦欢銆 * @grammar fetch( status ) => File * @method fetch * @param {String} status [鏂囦欢鐘舵€佸€糫(#WebUploader:File:File.Status) * @return {File} [File](#WebUploader:File) */ fetch: function( status ) { var len = this._queue.length, i, file; status = status || STATUS.QUEUED; for ( i = 0; i < len; i++ ) { file = this._queue[ i ]; if ( status === file.getStatus() ) { return file; } } return null; }, /** * 瀵归槦鍒楄繘琛屾帓搴忥紝鑳藉鎺у埗鏂囦欢涓婁紶椤哄簭銆 * @grammar sort( fn ) => undefined * @method sort * @param {Function} fn 鎺掑簭鏂规硶 */ sort: function( fn ) { if ( typeof fn === 'function' ) { this._queue.sort( fn ); } }, /** * 鑾峰彇鎸囧畾绫诲瀷鐨勬枃浠跺垪琛? 鍒楄〃涓瘡涓€涓垚鍛樹负[File](#WebUploader:File)瀵硅薄銆 * @grammar getFiles( [status1[, status2 ...]] ) => Array * @method getFiles * @param {String} [status] [鏂囦欢鐘舵€佸€糫(#WebUploader:File:File.Status) */ getFiles: function() { var sts = [].slice.call( arguments, 0 ), ret = [], i = 0, len = this._queue.length, file; for ( ; i < len; i++ ) { file = this._queue[ i ]; if ( sts.length && !~$.inArray( file.getStatus(), sts ) ) { continue; } ret.push( file ); } return ret; }, /** * 鍦ㄩ槦鍒椾腑鍒犻櫎鏂囦欢銆 * @grammar removeFile( file ) => Array * @method removeFile * @param {File} 鏂囦欢瀵硅薄銆 */ removeFile: function( file ) { var me = this, existing = this._map[ file.id ]; if ( existing ) { delete this._map[ file.id ]; file.destroy(); this.stats.numofDeleted++; } }, _fileAdded: function( file ) { var me = this, existing = this._map[ file.id ]; if ( !existing ) { this._map[ file.id ] = file; file.on( 'statuschange', function( cur, pre ) { me._onFileStatusChange( cur, pre ); }); } }, _onFileStatusChange: function( curStatus, preStatus ) { var stats = this.stats; switch ( preStatus ) { case STATUS.PROGRESS: stats.numOfProgress--; break; case STATUS.QUEUED: stats.numOfQueue --; break; case STATUS.ERROR: stats.numOfUploadFailed--; break; case STATUS.INVALID: stats.numOfInvalid--; break; case STATUS.INTERRUPT: stats.numofInterrupt--; break; } switch ( curStatus ) { case STATUS.QUEUED: stats.numOfQueue++; break; case STATUS.PROGRESS: stats.numOfProgress++; break; case STATUS.ERROR: stats.numOfUploadFailed++; break; case STATUS.COMPLETE: stats.numOfSuccess++; break; case STATUS.CANCELLED: stats.numOfCancel++; break; case STATUS.INVALID: stats.numOfInvalid++; break; case STATUS.INTERRUPT: stats.numofInterrupt++; break; } } }); Mediator.installTo( Queue.prototype ); return Queue; }); /** * @fileOverview 闃熷垪 */ define('widgets/queue',[ 'base', 'uploader', 'queue', 'file', 'lib/file', 'runtime/client', 'widgets/widget' ], function( Base, Uploader, Queue, WUFile, File, RuntimeClient ) { var $ = Base.$, rExt = /\.\w+$/, Status = WUFile.Status; return Uploader.register({ name: 'queue', init: function( opts ) { var me = this, deferred, len, i, item, arr, accept, runtime; if ( $.isPlainObject( opts.accept ) ) { opts.accept = [ opts.accept ]; } // accept涓殑涓敓鎴愬尮閰嶆鍒欍€ if ( opts.accept ) { arr = []; for ( i = 0, len = opts.accept.length; i < len; i++ ) { item = opts.accept[ i ].extensions; item && arr.push( item ); } if ( arr.length ) { accept = '\\.' + arr.join(',') .replace( /,/g, '$|\\.' ) .replace( /\*/g, '.*' ) + '$'; } me.accept = new RegExp( accept, 'i' ); } me.queue = new Queue(); me.stats = me.queue.stats; // 濡傛灉褰撳墠涓嶆槸html5杩愯鏃讹紝閭e氨绠椾簡銆 // 涓嶆墽琛屽悗缁搷浣 if ( this.request('predict-runtime-type') !== 'html5' ) { return; } // 鍒涘缓涓€涓 html5 杩愯鏃剁殑 placeholder // 浠ヨ嚦浜庡閮ㄦ坊鍔犲師鐢 File 瀵硅薄鐨勬椂鍊欒兘姝g‘鍖呰9涓€涓嬩緵 webuploader 浣跨敤銆 deferred = Base.Deferred(); this.placeholder = runtime = new RuntimeClient('Placeholder'); runtime.connectRuntime({ runtimeOrder: 'html5' }, function() { me._ruid = runtime.getRuid(); deferred.resolve(); }); return deferred.promise(); }, // 涓轰簡鏀寔澶栭儴鐩存帴娣诲姞涓€涓師鐢烣ile瀵硅薄銆 _wrapFile: function( file ) { if ( !(file instanceof WUFile) ) { if ( !(file instanceof File) ) { if ( !this._ruid ) { throw new Error('Can\'t add external files.'); } file = new File( this._ruid, file ); } file = new WUFile( file ); } return file; }, // 鍒ゆ柇鏂囦欢鏄惁鍙互琚姞鍏ラ槦鍒 acceptFile: function( file ) { var invalid = !file || !file.size || this.accept && // 濡傛灉鍚嶅瓧涓湁鍚庣紑锛屾墠鍋氬悗缂€鐧藉悕鍗曞鐞嗐€ rExt.exec( file.name ) && !this.accept.test( file.name ); return !invalid; }, /** * @event beforeFileQueued * @param {File} file File瀵硅薄 * @description 褰撴枃浠惰鍔犲叆闃熷垪涔嬪墠瑙﹀彂锛屾浜嬩欢鐨刪andler杩斿洖鍊间负`false`锛屽垯姝ゆ枃浠朵笉浼氳娣诲姞杩涘叆闃熷垪銆 * @for Uploader */ /** * @event fileQueued * @param {File} file File瀵硅薄 * @description 褰撴枃浠惰鍔犲叆闃熷垪浠ュ悗瑙﹀彂銆 * @for Uploader */ _addFile: function( file ) { var me = this; file = me._wrapFile( file ); // 涓嶈繃绫诲瀷鍒ゆ柇鍏佽涓嶅厑璁革紝鍏堟淳閫 `beforeFileQueued` if ( !me.owner.trigger( 'beforeFileQueued', file ) ) { return; } // 绫诲瀷涓嶅尮閰嶏紝鍒欐淳閫侀敊璇簨浠讹紝骞惰繑鍥炪€ if ( !me.acceptFile( file ) ) { me.owner.trigger( 'error', 'Q_TYPE_DENIED', file ); return; } me.queue.append( file ); me.owner.trigger( 'fileQueued', file ); return file; }, getFile: function( fileId ) { return this.queue.getFile( fileId ); }, /** * @event filesQueued * @param {File} files 鏁扮粍锛屽唴瀹逛负鍘熷File(lib/File锛夊璞°€ * @description 褰撲竴鎵规枃浠舵坊鍔犺繘闃熷垪浠ュ悗瑙﹀彂銆 * @for Uploader */ /** * @property {Boolean} [auto=false] * @namespace options * @for Uploader * @description 璁剧疆涓 true 鍚庯紝涓嶉渶瑕佹墜鍔ㄨ皟鐢ㄤ笂浼狅紝鏈夋枃浠堕€夋嫨鍗冲紑濮嬩笂浼犮€ * */ /** * @method addFiles * @grammar addFiles( file ) => undefined * @grammar addFiles( [file1, file2 ...] ) => undefined * @param {Array of File or File} [files] Files 瀵硅薄 鏁扮粍 * @description 娣诲姞鏂囦欢鍒伴槦鍒 * @for Uploader */ addFile: function( files ) { var me = this; if ( !files.length ) { files = [ files ]; } files = $.map( files, function( file ) { return me._addFile( file ); }); me.owner.trigger( 'filesQueued', files ); if ( me.options.auto ) { setTimeout(function() { me.request('start-upload'); }, 20 ); } }, getStats: function() { return this.stats; }, /** * @event fileDequeued * @param {File} file File瀵硅薄 * @description 褰撴枃浠惰绉婚櫎闃熷垪鍚庤Е鍙戙€ * @for Uploader */ /** * @method removeFile * @grammar removeFile( file ) => undefined * @grammar removeFile( id ) => undefined * @grammar removeFile( file, true ) => undefined * @grammar removeFile( id, true ) => undefined * @param {File|id} file File瀵硅薄鎴栬繖File瀵硅薄鐨刬d * @description 绉婚櫎鏌愪竴鏂囦欢, 榛樿鍙細鏍囪鏂囦欢鐘舵€佷负宸插彇娑堬紝濡傛灉绗簩涓弬鏁颁负 `true` 鍒欎細浠 queue 涓Щ闄ゃ€ * @for Uploader * @example * * $li.on('click', '.remove-this', function() { * uploader.removeFile( file ); * }) */ removeFile: function( file, remove ) { var me = this; file = file.id ? file : me.queue.getFile( file ); this.request( 'cancel-file', file ); if ( remove ) { this.queue.removeFile( file ); } }, /** * @method getFiles * @grammar getFiles() => Array * @grammar getFiles( status1, status2, status... ) => Array * @description 杩斿洖鎸囧畾鐘舵€佺殑鏂囦欢闆嗗悎锛屼笉浼犲弬鏁板皢杩斿洖鎵€鏈夌姸鎬佺殑鏂囦欢銆 * @for Uploader * @example * console.log( uploader.getFiles() ); // => all files * console.log( uploader.getFiles('error') ) // => all error files. */ getFiles: function() { return this.queue.getFiles.apply( this.queue, arguments ); }, fetchFile: function() { return this.queue.fetch.apply( this.queue, arguments ); }, /** * @method retry * @grammar retry() => undefined * @grammar retry( file ) => undefined * @description 閲嶈瘯涓婁紶锛岄噸璇曟寚瀹氭枃浠讹紝鎴栬€呬粠鍑洪敊鐨勬枃浠跺紑濮嬮噸鏂颁笂浼犮€ * @for Uploader * @example * function retry() { * uploader.retry(); * } */ retry: function( file, noForceStart ) { var me = this, files, i, len; if ( file ) { file = file.id ? file : me.queue.getFile( file ); file.setStatus( Status.QUEUED ); noForceStart || me.request('start-upload'); return; } files = me.queue.getFiles( Status.ERROR ); i = 0; len = files.length; for ( ; i < len; i++ ) { file = files[ i ]; file.setStatus( Status.QUEUED ); } me.request('start-upload'); }, /** * @method sort * @grammar sort( fn ) => undefined * @description 鎺掑簭闃熷垪涓殑鏂囦欢锛屽湪涓婁紶涔嬪墠璋冩暣鍙互鎺у埗涓婁紶椤哄簭銆 * @for Uploader */ sortFiles: function() { return this.queue.sort.apply( this.queue, arguments ); }, /** * @event reset * @description 褰 uploader 琚噸缃殑鏃跺€欒Е鍙戙€ * @for Uploader */ /** * @method reset * @grammar reset() => undefined * @description 閲嶇疆uploader銆傜洰鍓嶅彧閲嶇疆浜嗛槦鍒椼€ * @for Uploader * @example * uploader.reset(); */ reset: function() { this.owner.trigger('reset'); this.queue = new Queue(); this.stats = this.queue.stats; }, destroy: function() { this.reset(); this.placeholder && this.placeholder.destroy(); } }); }); /** * @fileOverview 娣诲姞鑾峰彇Runtime鐩稿叧淇℃伅鐨勬柟娉曘€ */ define('widgets/runtime',[ 'uploader', 'runtime/runtime', 'widgets/widget' ], function( Uploader, Runtime ) { Uploader.support = function() { return Runtime.hasRuntime.apply( Runtime, arguments ); }; /** * @property {Object} [runtimeOrder=html5,flash] * @namespace options * @for Uploader * @description 鎸囧畾杩愯鏃跺惎鍔ㄩ『搴忋€傞粯璁や細鎯冲皾璇 html5 鏄惁鏀寔锛屽鏋滄敮鎸佸垯浣跨敤 html5, 鍚﹀垯鍒欎娇鐢 flash. * * 鍙互灏嗘鍊艰缃垚 `flash`锛屾潵寮哄埗浣跨敤 flash 杩愯鏃躲€ */ return Uploader.register({ name: 'runtime', init: function() { if ( !this.predictRuntimeType() ) { throw Error('Runtime Error'); } }, /** * 棰勬祴Uploader灏嗛噰鐢ㄥ摢涓猔Runtime` * @grammar predictRuntimeType() => String * @method predictRuntimeType * @for Uploader */ predictRuntimeType: function() { var orders = this.options.runtimeOrder || Runtime.orders, type = this.type, i, len; if ( !type ) { orders = orders.split( /\s*,\s*/g ); for ( i = 0, len = orders.length; i < len; i++ ) { if ( Runtime.hasRuntime( orders[ i ] ) ) { this.type = type = orders[ i ]; break; } } } return type; } }); }); /** * @fileOverview Transport */ define('lib/transport',[ 'base', 'runtime/client', 'mediator' ], function( Base, RuntimeClient, Mediator ) { var $ = Base.$; function Transport( opts ) { var me = this; opts = me.options = $.extend( true, {}, Transport.options, opts || {} ); RuntimeClient.call( this, 'Transport' ); this._blob = null; this._formData = opts.formData || {}; this._headers = opts.headers || {}; this.on( 'progress', this._timeout ); this.on( 'load error', function() { me.trigger( 'progress', 1 ); clearTimeout( me._timer ); }); } Transport.options = { server: '', method: 'POST', // 璺ㄥ煙鏃讹紝鏄惁鍏佽鎼哄甫cookie, 鍙湁html5 runtime鎵嶆湁鏁 withCredentials: false, fileVal: 'file', timeout: 2 * 60 * 1000, // 2鍒嗛挓 formData: {}, headers: {}, sendAsBinary: false }; $.extend( Transport.prototype, { // 娣诲姞Blob, 鍙兘娣诲姞涓€娆★紝鏈€鍚庝竴娆℃湁鏁堛€ appendBlob: function( key, blob, filename ) { var me = this, opts = me.options; if ( me.getRuid() ) { me.disconnectRuntime(); } // 杩炴帴鍒癰lob褰掑睘鐨勫悓涓€涓猺untime. me.connectRuntime( blob.ruid, function() { me.exec('init'); }); me._blob = blob; opts.fileVal = key || opts.fileVal; opts.filename = filename || opts.filename; }, // 娣诲姞鍏朵粬瀛楁 append: function( key, value ) { if ( typeof key === 'object' ) { $.extend( this._formData, key ); } else { this._formData[ key ] = value; } }, setRequestHeader: function( key, value ) { if ( typeof key === 'object' ) { $.extend( this._headers, key ); } else { this._headers[ key ] = value; } }, send: function( method ) { this.exec( 'send', method ); this._timeout(); }, abort: function() { clearTimeout( this._timer ); return this.exec('abort'); }, destroy: function() { this.trigger('destroy'); this.off(); this.exec('destroy'); this.disconnectRuntime(); }, getResponse: function() { return this.exec('getResponse'); }, getResponseAsJson: function() { return this.exec('getResponseAsJson'); }, getStatus: function() { return this.exec('getStatus'); }, _timeout: function() { var me = this, duration = me.options.timeout; if ( !duration ) { return; } clearTimeout( me._timer ); me._timer = setTimeout(function() { me.abort(); me.trigger( 'error', 'timeout' ); }, duration ); } }); // 璁㏕ransport鍏峰浜嬩欢鍔熻兘銆 Mediator.installTo( Transport.prototype ); return Transport; }); /** * @fileOverview 璐熻矗鏂囦欢涓婁紶鐩稿叧銆 */ define('widgets/upload',[ 'base', 'uploader', 'file', 'lib/transport', 'widgets/widget' ], function( Base, Uploader, WUFile, Transport ) { var $ = Base.$, isPromise = Base.isPromise, Status = WUFile.Status; // 娣诲姞榛樿閰嶇疆椤 $.extend( Uploader.options, { /** * @property {Boolean} [prepareNextFile=false] * @namespace options * @for Uploader * @description 鏄惁鍏佽鍦ㄦ枃浠朵紶杈撴椂鎻愬墠鎶婁笅涓€涓枃浠跺噯澶囧ソ銆 * 瀵逛簬涓€涓枃浠剁殑鍑嗗宸ヤ綔姣旇緝鑰楁椂锛屾瘮濡傚浘鐗囧帇缂╋紝md5搴忓垪鍖栥€ * 濡傛灉鑳芥彁鍓嶅湪褰撳墠鏂囦欢浼犺緭鏈熷鐞嗭紝鍙互鑺傜渷鎬讳綋鑰楁椂銆 */ prepareNextFile: false, /** * @property {Boolean} [chunked=false] * @namespace options * @for Uploader * @description 鏄惁瑕佸垎鐗囧鐞嗗ぇ鏂囦欢涓婁紶銆 */ chunked: false, /** * @property {Boolean} [chunkSize=5242880] * @namespace options * @for Uploader * @description 濡傛灉瑕佸垎鐗囷紝鍒嗗澶т竴鐗囷紵 榛樿澶у皬涓?M. */ chunkSize: 5 * 1024 * 1024, /** * @property {Boolean} [chunkRetry=2] * @namespace options * @for Uploader * @description 濡傛灉鏌愪釜鍒嗙墖鐢变簬缃戠粶闂鍑洪敊锛屽厑璁歌嚜鍔ㄩ噸浼犲灏戞锛 */ chunkRetry: 2, /** * @property {Boolean} [threads=3] * @namespace options * @for Uploader * @description 涓婁紶骞跺彂鏁般€傚厑璁稿悓鏃舵渶澶т笂浼犺繘绋嬫暟銆 */ threads: 3, /** * @property {Object} [formData={}] * @namespace options * @for Uploader * @description 鏂囦欢涓婁紶璇锋眰鐨勫弬鏁拌〃锛屾瘡娆″彂閫侀兘浼氬彂閫佹瀵硅薄涓殑鍙傛暟銆 */ formData: {} /** * @property {Object} [fileVal='file'] * @namespace options * @for Uploader * @description 璁剧疆鏂囦欢涓婁紶鍩熺殑name銆 */ /** * @property {Object} [method='POST'] * @namespace options * @for Uploader * @description 鏂囦欢涓婁紶鏂瑰紡锛宍POST`鎴栬€卄GET`銆 */ /** * @property {Object} [sendAsBinary=false] * @namespace options * @for Uploader * @description 鏄惁宸蹭簩杩涘埗鐨勬祦鐨勬柟寮忓彂閫佹枃浠讹紝杩欐牱鏁翠釜涓婁紶鍐呭`php://input`閮戒负鏂囦欢鍐呭锛 * 鍏朵粬鍙傛暟鍦?_GET鏁扮粍涓€ */ }); // 璐熻矗灏嗘枃浠跺垏鐗囥€ function CuteFile( file, chunkSize ) { var pending = [], blob = file.source, total = blob.size, chunks = chunkSize ? Math.ceil( total / chunkSize ) : 1, start = 0, index = 0, len, api; api = { file: file, has: function() { return !!pending.length; }, shift: function() { return pending.shift(); }, unshift: function( block ) { pending.unshift( block ); } }; while ( index < chunks ) { len = Math.min( chunkSize, total - start ); pending.push({ file: file, start: start, end: chunkSize ? (start + len) : total, total: total, chunks: chunks, chunk: index++, cuted: api }); start += len; } file.blocks = pending.concat(); file.remaning = pending.length; return api; } Uploader.register({ name: 'upload', init: function() { var owner = this.owner, me = this; this.runing = false; this.progress = false; owner .on( 'startUpload', function() { me.progress = true; }) .on( 'uploadFinished', function() { me.progress = false; }); // 璁板綍褰撳墠姝e湪浼犵殑鏁版嵁锛岃窡threads鐩稿叧 this.pool = []; // 缂撳瓨鍒嗗ソ鐗囩殑鏂囦欢銆 this.stack = []; // 缂撳瓨鍗冲皢涓婁紶鐨勬枃浠躲€ this.pending = []; // 璺熻釜杩樻湁澶氬皯鍒嗙墖鍦ㄤ笂浼犱腑浣嗘槸娌℃湁瀹屾垚涓婁紶銆 this.remaning = 0; this.__tick = Base.bindFn( this._tick, this ); owner.on( 'uploadComplete', function( file ) { // 鎶婂叾浠栧潡鍙栨秷浜嗐€ file.blocks && $.each( file.blocks, function( _, v ) { v.transport && (v.transport.abort(), v.transport.destroy()); delete v.transport; }); delete file.blocks; delete file.remaning; }); }, reset: function() { this.request( 'stop-upload', true ); this.runing = false; this.pool = []; this.stack = []; this.pending = []; this.remaning = 0; this._trigged = false; this._promise = null; }, /** * @event startUpload * @description 褰撳紑濮嬩笂浼犳祦绋嬫椂瑙﹀彂銆 * @for Uploader */ /** * 寮€濮嬩笂浼犮€傛鏂规硶鍙互浠庡垵濮嬬姸鎬佽皟鐢ㄥ紑濮嬩笂浼犳祦绋嬶紝涔熷彲浠ヤ粠鏆傚仠鐘舵€佽皟鐢紝缁х画涓婁紶娴佺▼銆 * * 鍙互鎸囧畾寮€濮嬫煇涓€涓枃浠躲€ * @grammar upload() => undefined * @grammar upload( file | fileId) => undefined * @method upload * @for Uploader */ startUpload: function(file) { var me = this; // 绉诲嚭invalid鐨勬枃浠 $.each( me.request( 'get-files', Status.INVALID ), function() { me.request( 'remove-file', this ); }); // 濡傛灉鎸囧畾浜嗗紑濮嬫煇涓枃浠讹紝鍒欏彧寮€濮嬫寚瀹氭枃浠躲€ if ( file ) { file = file.id ? file : me.request( 'get-file', file ); if (file.getStatus() === Status.INTERRUPT) { $.each( me.pool, function( _, v ) { // 涔嬪墠鏆傚仠杩囥€ if (v.file !== file) { return; } v.transport && v.transport.send(); }); file.setStatus( Status.QUEUED ); } else if (file.getStatus() === Status.PROGRESS) { return; } else { file.setStatus( Status.QUEUED ); } } else { $.each( me.request( 'get-files', [ Status.INITED ] ), function() { this.setStatus( Status.QUEUED ); }); } if ( me.runing ) { return; } me.runing = true; var files = []; // 濡傛灉鏈夋殏鍋滅殑锛屽垯缁紶 $.each( me.pool, function( _, v ) { var file = v.file; if ( file.getStatus() === Status.INTERRUPT ) { files.push(file); me._trigged = false; v.transport && v.transport.send(); } }); var file; while ( (file = files.shift()) ) { file.setStatus( Status.PROGRESS ); } file || $.each( me.request( 'get-files', Status.INTERRUPT ), function() { this.setStatus( Status.PROGRESS ); }); me._trigged = false; Base.nextTick( me.__tick ); me.owner.trigger('startUpload'); }, /** * @event stopUpload * @description 褰撳紑濮嬩笂浼犳祦绋嬫殏鍋滄椂瑙﹀彂銆 * @for Uploader */ /** * 鏆傚仠涓婁紶銆傜涓€涓弬鏁颁负鏄惁涓柇涓婁紶褰撳墠姝e湪涓婁紶鐨勬枃浠躲€ * * 濡傛灉绗竴涓弬鏁版槸鏂囦欢锛屽垯鍙殏鍋滄寚瀹氭枃浠躲€ * @grammar stop() => undefined * @grammar stop( true ) => undefined * @grammar stop( file ) => undefined * @method stop * @for Uploader */ stopUpload: function( file, interrupt ) { var me = this; if (file === true) { interrupt = file; file = null; } if ( me.runing === false ) { return; } // 濡傛灉鍙槸鏆傚仠鏌愪釜鏂囦欢銆 if ( file ) { file = file.id ? file : me.request( 'get-file', file ); if ( file.getStatus() !== Status.PROGRESS && file.getStatus() !== Status.QUEUED ) { return; } file.setStatus( Status.INTERRUPT ); $.each( me.pool, function( _, v ) { // 鍙 abort 鎸囧畾鐨勬枃浠躲€ if (v.file !== file) { return; } v.transport && v.transport.abort(); me._putback(v); me._popBlock(v); }); return Base.nextTick( me.__tick ); } me.runing = false; if (this._promise && this._promise.file) { this._promise.file.setStatus( Status.INTERRUPT ); } interrupt && $.each( me.pool, function( _, v ) { v.transport && v.transport.abort(); v.file.setStatus( Status.INTERRUPT ); }); me.owner.trigger('stopUpload'); }, /** * @method cancelFile * @grammar cancelFile( file ) => undefined * @grammar cancelFile( id ) => undefined * @param {File|id} file File瀵硅薄鎴栬繖File瀵硅薄鐨刬d * @description 鏍囪鏂囦欢鐘舵€佷负宸插彇娑? 鍚屾椂灏嗕腑鏂枃浠朵紶杈撱€ * @for Uploader * @example * * $li.on('click', '.remove-this', function() { * uploader.cancelFile( file ); * }) */ cancelFile: function( file ) { file = file.id ? file : this.request( 'get-file', file ); // 濡傛灉姝e湪涓婁紶銆 file.blocks && $.each( file.blocks, function( _, v ) { var _tr = v.transport; if ( _tr ) { _tr.abort(); _tr.destroy(); delete v.transport; } }); file.setStatus( Status.CANCELLED ); this.owner.trigger( 'fileDequeued', file ); }, /** * 鍒ゆ柇`Uplaode`r鏄惁姝e湪涓婁紶涓€ * @grammar isInProgress() => Boolean * @method isInProgress * @for Uploader */ isInProgress: function() { return !!this.progress; }, _getStats: function() { return this.request('get-stats'); }, /** * 鎺夎繃涓€涓枃浠朵笂浼狅紝鐩存帴鏍囪鎸囧畾鏂囦欢涓哄凡涓婁紶鐘舵€併€ * @grammar skipFile( file ) => undefined * @method skipFile * @for Uploader */ skipFile: function( file, status ) { file = file.id ? file : this.request( 'get-file', file ); file.setStatus( status || Status.COMPLETE ); file.skipped = true; // 濡傛灉姝e湪涓婁紶銆 file.blocks && $.each( file.blocks, function( _, v ) { var _tr = v.transport; if ( _tr ) { _tr.abort(); _tr.destroy(); delete v.transport; } }); this.owner.trigger( 'uploadSkip', file ); }, /** * @event uploadFinished * @description 褰撴墍鏈夋枃浠朵笂浼犵粨鏉熸椂瑙﹀彂銆 * @for Uploader */ _tick: function() { var me = this, opts = me.options, fn, val; // 涓婁竴涓猵romise杩樻病鏈夌粨鏉燂紝鍒欑瓑寰呭畬鎴愬悗鍐嶆墽琛屻€ if ( me._promise ) { return me._promise.always( me.__tick ); } // 杩樻湁浣嶇疆锛屼笖杩樻湁鏂囦欢瑕佸鐞嗙殑璇濄€ if ( me.pool.length < opts.threads && (val = me._nextBlock()) ) { me._trigged = false; fn = function( val ) { me._promise = null; // 鏈夊彲鑳芥槸reject杩囨潵鐨勶紝鎵€浠ヨ妫€娴媣al鐨勭被鍨嬨€ val && val.file && me._startSend( val ); Base.nextTick( me.__tick ); }; me._promise = isPromise( val ) ? val.always( fn ) : fn( val ); // 娌℃湁瑕佷笂浼犵殑浜嗭紝涓旀病鏈夋鍦ㄤ紶杈撶殑浜嗐€ } else if ( !me.remaning && !me._getStats().numOfQueue && !me._getStats().numofInterrupt ) { me.runing = false; me._trigged || Base.nextTick(function() { me.owner.trigger('uploadFinished'); }); me._trigged = true; } }, _putback: function(block) { var idx; block.cuted.unshift(block); idx = this.stack.indexOf(block.cuted); if (!~idx) { this.stack.unshift(block.cuted); } }, _getStack: function() { var i = 0, act; while ( (act = this.stack[ i++ ]) ) { if ( act.has() && act.file.getStatus() === Status.PROGRESS ) { return act; } else if (!act.has() || act.file.getStatus() !== Status.PROGRESS && act.file.getStatus() !== Status.INTERRUPT ) { // 鎶婂凡缁忓鐞嗗畬浜嗙殑锛屾垨鑰咃紝鐘舵€佷负闈 progress锛堜笂浼犱腑锛夈€ // interupt锛堟殏鍋滀腑锛 鐨勭Щ闄ゃ€ this.stack.splice( --i, 1 ); } } return null; }, _nextBlock: function() { var me = this, opts = me.options, act, next, done, preparing; // 濡傛灉褰撳墠鏂囦欢杩樻湁娌℃湁闇€瑕佷紶杈撶殑锛屽垯鐩存帴杩斿洖鍓╀笅鐨勩€ if ( (act = this._getStack()) ) { // 鏄惁鎻愬墠鍑嗗涓嬩竴涓枃浠 if ( opts.prepareNextFile && !me.pending.length ) { me._prepareNextFile(); } return act.shift(); // 鍚﹀垯锛屽鏋滄鍦ㄨ繍琛岋紝鍒欏噯澶囦笅涓€涓枃浠讹紝骞剁瓑寰呭畬鎴愬悗杩斿洖涓嬩釜鍒嗙墖銆 } else if ( me.runing ) { // 濡傛灉缂撳瓨涓湁锛屽垯鐩存帴鍦ㄧ紦瀛樹腑鍙栵紝娌℃湁鍒欏幓queue涓彇銆 if ( !me.pending.length && me._getStats().numOfQueue ) { me._prepareNextFile(); } next = me.pending.shift(); done = function( file ) { if ( !file ) { return null; } act = CuteFile( file, opts.chunked ? opts.chunkSize : 0 ); me.stack.push(act); return act.shift(); }; // 鏂囦欢鍙兘杩樺湪prepare涓紝涔熸湁鍙兘宸茬粡瀹屽叏鍑嗗濂戒簡銆 if ( isPromise( next) ) { preparing = next.file; next = next[ next.pipe ? 'pipe' : 'then' ]( done ); next.file = preparing; return next; } return done( next ); } }, /** * @event uploadStart * @param {File} file File瀵硅薄 * @description 鏌愪釜鏂囦欢寮€濮嬩笂浼犲墠瑙﹀彂锛屼竴涓枃浠跺彧浼氳Е鍙戜竴娆°€ * @for Uploader */ _prepareNextFile: function() { var me = this, file = me.request('fetch-file'), pending = me.pending, promise; if ( file ) { promise = me.request( 'before-send-file', file, function() { // 鏈夊彲鑳芥枃浠惰skip鎺変簡銆傛枃浠惰skip鎺夊悗锛岀姸鎬佸潙瀹氫笉鏄疩ueued. if ( file.getStatus() === Status.PROGRESS || file.getStatus() === Status.INTERRUPT ) { return file; } return me._finishFile( file ); }); me.owner.trigger( 'uploadStart', file ); file.setStatus( Status.PROGRESS ); promise.file = file; // 濡傛灉杩樺湪pending涓紝鍒欐浛鎹㈡垚鏂囦欢鏈韩銆 promise.done(function() { var idx = $.inArray( promise, pending ); ~idx && pending.splice( idx, 1, file ); }); // befeore-send-file鐨勯挬瀛愬氨鏈夐敊璇彂鐢熴€ promise.fail(function( reason ) { file.setStatus( Status.ERROR, reason ); me.owner.trigger( 'uploadError', file, reason ); me.owner.trigger( 'uploadComplete', file ); }); pending.push( promise ); } }, // 璁╁嚭浣嶇疆浜嗭紝鍙互璁╁叾浠栧垎鐗囧紑濮嬩笂浼 _popBlock: function( block ) { var idx = $.inArray( block, this.pool ); this.pool.splice( idx, 1 ); block.file.remaning--; this.remaning--; }, // 寮€濮嬩笂浼狅紝鍙互琚帀杩囥€傚鏋減romise琚玶eject浜嗭紝鍒欒〃绀鸿烦杩囨鍒嗙墖銆 _startSend: function( block ) { var me = this, file = block.file, promise; // 鏈夊彲鑳藉湪 before-send-file 鐨 promise 鏈熼棿鏀瑰彉浜嗘枃浠剁姸鎬併€ // 濡傦細鏆傚仠锛屽彇娑 // 鎴戜滑涓嶈兘涓柇 promise, 浣嗘槸鍙互鍦 promise 瀹屽悗锛屼笉鍋氫笂浼犳搷浣溿€ if ( file.getStatus() !== Status.PROGRESS ) { // 濡傛灉鏄腑鏂紝鍒欒繕闇€瑕佹斁鍥炲幓銆 if (file.getStatus() === Status.INTERRUPT) { me._putback(block); } return; } me.pool.push( block ); me.remaning++; // 濡傛灉娌℃湁鍒嗙墖锛屽垯鐩存帴浣跨敤鍘熷鐨勩€ // 涓嶄細涓㈠けcontent-type淇℃伅銆 block.blob = block.chunks === 1 ? file.source : file.source.slice( block.start, block.end ); // hook, 姣忎釜鍒嗙墖鍙戦€佷箣鍓嶅彲鑳借鍋氫簺寮傛鐨勪簨鎯呫€ promise = me.request( 'before-send', block, function() { // 鏈夊彲鑳芥枃浠跺凡缁忎笂浼犲嚭閿欎簡锛屾墍浠ヤ笉闇€瑕佸啀浼犺緭浜嗐€ if ( file.getStatus() === Status.PROGRESS ) { me._doSend( block ); } else { me._popBlock( block ); Base.nextTick( me.__tick ); } }); // 濡傛灉涓篺ail浜嗭紝鍒欒烦杩囨鍒嗙墖銆 promise.fail(function() { if ( file.remaning === 1 ) { me._finishFile( file ).always(function() { block.percentage = 1; me._popBlock( block ); me.owner.trigger( 'uploadComplete', file ); Base.nextTick( me.__tick ); }); } else { block.percentage = 1; me.updateFileProgress( file ); me._popBlock( block ); Base.nextTick( me.__tick ); } }); }, /** * @event uploadBeforeSend * @param {Object} object * @param {Object} data 榛樿鐨勪笂浼犲弬鏁帮紝鍙互鎵╁睍姝ゅ璞℃潵鎺у埗涓婁紶鍙傛暟銆 * @param {Object} headers 鍙互鎵╁睍姝ゅ璞℃潵鎺у埗涓婁紶澶撮儴銆 * @description 褰撴煇涓枃浠剁殑鍒嗗潡鍦ㄥ彂閫佸墠瑙﹀彂锛屼富瑕佺敤鏉ヨ闂槸鍚﹁娣诲姞闄勫甫鍙傛暟锛屽ぇ鏂囦欢鍦ㄥ紑璧峰垎鐗囦笂浼犵殑鍓嶆彁涓嬫浜嬩欢鍙兘浼氳Е鍙戝娆°€ * @for Uploader */ /** * @event uploadAccept * @param {Object} object * @param {Object} ret 鏈嶅姟绔殑杩斿洖鏁版嵁锛宩son鏍煎紡锛屽鏋滄湇鍔$涓嶆槸json鏍煎紡锛屼粠ret._raw涓彇鏁版嵁锛岃嚜琛岃В鏋愩€ * @description 褰撴煇涓枃浠朵笂浼犲埌鏈嶅姟绔搷搴斿悗锛屼細娲鹃€佹浜嬩欢鏉ヨ闂湇鍔$鍝嶅簲鏄惁鏈夋晥銆傚鏋滄浜嬩欢handler杩斿洖鍊间负`false`, 鍒欐鏂囦欢灏嗘淳閫乣server`绫诲瀷鐨刞uploadError`浜嬩欢銆 * @for Uploader */ /** * @event uploadProgress * @param {File} file File瀵硅薄 * @param {Number} percentage 涓婁紶杩涘害 * @description 涓婁紶杩囩▼涓Е鍙戯紝鎼哄甫涓婁紶杩涘害銆 * @for Uploader */ /** * @event uploadError * @param {File} file File瀵硅薄 * @param {String} reason 鍑洪敊鐨刢ode * @description 褰撴枃浠朵笂浼犲嚭閿欐椂瑙﹀彂銆 * @for Uploader */ /** * @event uploadSuccess * @param {File} file File瀵硅薄 * @param {Object} response 鏈嶅姟绔繑鍥炵殑鏁版嵁 * @description 褰撴枃浠朵笂浼犳垚鍔熸椂瑙﹀彂銆 * @for Uploader */ /** * @event uploadComplete * @param {File} [file] File瀵硅薄 * @description 涓嶇鎴愬姛鎴栬€呭け璐ワ紝鏂囦欢涓婁紶瀹屾垚鏃惰Е鍙戙€ * @for Uploader */ // 鍋氫笂浼犳搷浣溿€ _doSend: function( block ) { var me = this, owner = me.owner, opts = me.options, file = block.file, tr = new Transport( opts ), data = $.extend({}, opts.formData ), headers = $.extend({}, opts.headers ), requestAccept, ret; block.transport = tr; tr.on( 'destroy', function() { delete block.transport; me._popBlock( block ); Base.nextTick( me.__tick ); }); // 骞挎挱涓婁紶杩涘害銆備互鏂囦欢涓哄崟浣嶃€ tr.on( 'progress', function( percentage ) { block.percentage = percentage; me.updateFileProgress( file ); }); // 鐢ㄦ潵璇㈤棶锛屾槸鍚﹁繑鍥炵殑缁撴灉鏄湁閿欒鐨勩€ requestAccept = function( reject ) { var fn; ret = tr.getResponseAsJson() || {}; ret._raw = tr.getResponse(); fn = function( value ) { reject = value; }; // 鏈嶅姟绔搷搴斾簡锛屼笉浠h〃鎴愬姛浜嗭紝璇㈤棶鏄惁鍝嶅簲姝g‘銆 if ( !owner.trigger( 'uploadAccept', block, ret, fn ) ) { reject = reject || 'server'; } return reject; }; // 灏濊瘯閲嶈瘯锛岀劧鍚庡箍鎾枃浠朵笂浼犲嚭閿欍€ tr.on( 'error', function( type, flag ) { block.retried = block.retried || 0; // 鑷姩閲嶈瘯 if ( block.chunks > 1 && ~'http,abort'.indexOf( type ) && block.retried < opts.chunkRetry ) { block.retried++; tr.send(); } else { // http status 500 ~ 600 if ( !flag && type === 'server' ) { type = requestAccept( type ); } file.setStatus( Status.ERROR, type ); owner.trigger( 'uploadError', file, type ); owner.trigger( 'uploadComplete', file ); } }); // 涓婁紶鎴愬姛 tr.on( 'load', function() { var reason; // 濡傛灉闈為鏈燂紝杞悜涓婁紶鍑洪敊銆 if ( (reason = requestAccept()) ) { tr.trigger( 'error', reason, true ); return; } // 鍏ㄩ儴涓婁紶瀹屾垚銆 if ( file.remaning === 1 ) { me._finishFile( file, ret ); } else { tr.destroy(); } }); // 閰嶇疆榛樿鐨勪笂浼犲瓧娈点€ data = $.extend( data, { id: file.id, name: file.name, type: file.type, lastModifiedDate: file.lastModifiedDate, size: file.size }); block.chunks > 1 && $.extend( data, { chunks: block.chunks, chunk: block.chunk }); // 鍦ㄥ彂閫佷箣闂村彲浠ユ坊鍔犲瓧娈典粈涔堢殑銆傘€傘€ // 濡傛灉榛樿鐨勫瓧娈典笉澶熶娇鐢紝鍙互閫氳繃鐩戝惉姝や簨浠舵潵鎵╁睍 owner.trigger( 'uploadBeforeSend', block, data, headers ); // 寮€濮嬪彂閫併€ tr.appendBlob( opts.fileVal, block.blob, file.name ); tr.append( data ); tr.setRequestHeader( headers ); tr.send(); }, // 瀹屾垚涓婁紶銆 _finishFile: function( file, ret, hds ) { var owner = this.owner; return owner .request( 'after-send-file', arguments, function() { file.setStatus( Status.COMPLETE ); owner.trigger( 'uploadSuccess', file, ret, hds ); }) .fail(function( reason ) { // 濡傛灉澶栭儴宸茬粡鏍囪涓篿nvalid浠€涔堢殑锛屼笉鍐嶆敼鐘舵€併€ if ( file.getStatus() === Status.PROGRESS ) { file.setStatus( Status.ERROR, reason ); } owner.trigger( 'uploadError', file, reason ); }) .always(function() { owner.trigger( 'uploadComplete', file ); }); }, updateFileProgress: function(file) { var totalPercent = 0, uploaded = 0; if (!file.blocks) { return; } $.each( file.blocks, function( _, v ) { uploaded += (v.percentage || 0) * (v.end - v.start); }); totalPercent = uploaded / file.size; this.owner.trigger( 'uploadProgress', file, totalPercent || 0 ); } }); }); /** * @fileOverview 鍚勭楠岃瘉锛屽寘鎷枃浠舵€诲ぇ灏忔槸鍚﹁秴鍑恒€佸崟鏂囦欢鏄惁瓒呭嚭鍜屾枃浠舵槸鍚﹂噸澶嶃€ */ define('widgets/validator',[ 'base', 'uploader', 'file', 'widgets/widget' ], function( Base, Uploader, WUFile ) { var $ = Base.$, validators = {}, api; /** * @event error * @param {String} type 閿欒绫诲瀷銆 * @description 褰搗alidate涓嶉€氳繃鏃讹紝浼氫互娲鹃€侀敊璇簨浠剁殑褰㈠紡閫氱煡璋冪敤鑰呫€傞€氳繃`upload.on('error', handler)`鍙互鎹曡幏鍒版绫婚敊璇紝鐩墠鏈変互涓嬮敊璇細鍦ㄧ壒瀹氱殑鎯呭喌涓嬫淳閫侀敊鏉ャ€ * * * `Q_EXCEED_NUM_LIMIT` 鍦ㄨ缃簡`fileNumLimit`涓斿皾璇曠粰`uploader`娣诲姞鐨勬枃浠舵暟閲忚秴鍑鸿繖涓€兼椂娲鹃€併€ * * `Q_EXCEED_SIZE_LIMIT` 鍦ㄨ缃簡`Q_EXCEED_SIZE_LIMIT`涓斿皾璇曠粰`uploader`娣诲姞鐨勬枃浠舵€诲ぇ灏忚秴鍑鸿繖涓€兼椂娲鹃€併€ * * `Q_TYPE_DENIED` 褰撴枃浠剁被鍨嬩笉婊¤冻鏃惰Е鍙戙€傘€ * @for Uploader */ // 鏆撮湶缁欏闈㈢殑api api = { // 娣诲姞楠岃瘉鍣 addValidator: function( type, cb ) { validators[ type ] = cb; }, // 绉婚櫎楠岃瘉鍣 removeValidator: function( type ) { delete validators[ type ]; } }; // 鍦║ploader鍒濆鍖栫殑鏃跺€欏惎鍔╒alidators鐨勫垵濮嬪寲 Uploader.register({ name: 'validator', init: function() { var me = this; Base.nextTick(function() { $.each( validators, function() { this.call( me.owner ); }); }); } }); /** * @property {int} [fileNumLimit=undefined] * @namespace options * @for Uploader * @description 楠岃瘉鏂囦欢鎬绘暟閲? 瓒呭嚭鍒欎笉鍏佽鍔犲叆闃熷垪銆 */ api.addValidator( 'fileNumLimit', function() { var uploader = this, opts = uploader.options, count = 0, max = parseInt( opts.fileNumLimit, 10 ), flag = true; if ( !max ) { return; } uploader.on( 'beforeFileQueued', function( file ) { if ( count >= max && flag ) { flag = false; this.trigger( 'error', 'Q_EXCEED_NUM_LIMIT', max, file ); setTimeout(function() { flag = true; }, 1 ); } return count >= max ? false : true; }); uploader.on( 'fileQueued', function() { count++; }); uploader.on( 'fileDequeued', function() { count--; }); uploader.on( 'reset', function() { count = 0; }); }); /** * @property {int} [fileSizeLimit=undefined] * @namespace options * @for Uploader * @description 楠岃瘉鏂囦欢鎬诲ぇ灏忔槸鍚﹁秴鍑洪檺鍒? 瓒呭嚭鍒欎笉鍏佽鍔犲叆闃熷垪銆 */ api.addValidator( 'fileSizeLimit', function() { var uploader = this, opts = uploader.options, count = 0, max = parseInt( opts.fileSizeLimit, 10 ), flag = true; if ( !max ) { return; } uploader.on( 'beforeFileQueued', function( file ) { var invalid = count + file.size > max; if ( invalid && flag ) { flag = false; this.trigger( 'error', 'Q_EXCEED_SIZE_LIMIT', max, file ); setTimeout(function() { flag = true; }, 1 ); } return invalid ? false : true; }); uploader.on( 'fileQueued', function( file ) { count += file.size; }); uploader.on( 'fileDequeued', function( file ) { count -= file.size; }); uploader.on( 'reset', function() { count = 0; }); }); /** * @property {int} [fileSingleSizeLimit=undefined] * @namespace options * @for Uploader * @description 楠岃瘉鍗曚釜鏂囦欢澶у皬鏄惁瓒呭嚭闄愬埗, 瓒呭嚭鍒欎笉鍏佽鍔犲叆闃熷垪銆 */ api.addValidator( 'fileSingleSizeLimit', function() { var uploader = this, opts = uploader.options, max = opts.fileSingleSizeLimit; if ( !max ) { return; } uploader.on( 'beforeFileQueued', function( file ) { if ( file.size > max ) { file.setStatus( WUFile.Status.INVALID, 'exceed_size' ); this.trigger( 'error', 'F_EXCEED_SIZE', max, file ); return false; } }); }); /** * @property {Boolean} [duplicate=undefined] * @namespace options * @for Uploader * @description 鍘婚噸锛 鏍规嵁鏂囦欢鍚嶅瓧銆佹枃浠跺ぇ灏忓拰鏈€鍚庝慨鏀规椂闂存潵鐢熸垚hash Key. */ api.addValidator( 'duplicate', function() { var uploader = this, opts = uploader.options, mapping = {}; if ( opts.duplicate ) { return; } function hashString( str ) { var hash = 0, i = 0, len = str.length, _char; for ( ; i < len; i++ ) { _char = str.charCodeAt( i ); hash = _char + (hash << 6) + (hash << 16) - hash; } return hash; } uploader.on( 'beforeFileQueued', function( file ) { var hash = file.__hash || (file.__hash = hashString( file.name + file.size + file.lastModifiedDate )); // 宸茬粡閲嶅浜 if ( mapping[ hash ] ) { this.trigger( 'error', 'F_DUPLICATE', file ); return false; } }); uploader.on( 'fileQueued', function( file ) { var hash = file.__hash; hash && (mapping[ hash ] = true); }); uploader.on( 'fileDequeued', function( file ) { var hash = file.__hash; hash && (delete mapping[ hash ]); }); uploader.on( 'reset', function() { mapping = {}; }); }); return api; }); /** * @fileOverview Md5 */ define('lib/md5',[ 'runtime/client', 'mediator' ], function( RuntimeClient, Mediator ) { function Md5() { RuntimeClient.call( this, 'Md5' ); } // 璁 Md5 鍏峰浜嬩欢鍔熻兘銆 Mediator.installTo( Md5.prototype ); Md5.prototype.loadFromBlob = function( blob ) { var me = this; if ( me.getRuid() ) { me.disconnectRuntime(); } // 杩炴帴鍒癰lob褰掑睘鐨勫悓涓€涓猺untime. me.connectRuntime( blob.ruid, function() { me.exec('init'); me.exec( 'loadFromBlob', blob ); }); }; Md5.prototype.getResult = function() { return this.exec('getResult'); }; return Md5; }); /** * @fileOverview 鍥剧墖鎿嶄綔, 璐熻矗棰勮鍥剧墖鍜屼笂浼犲墠鍘嬬缉鍥剧墖 */ define('widgets/md5',[ 'base', 'uploader', 'lib/md5', 'lib/blob', 'widgets/widget' ], function( Base, Uploader, Md5, Blob ) { return Uploader.register({ name: 'md5', /** * 璁$畻鏂囦欢 md5 鍊硷紝杩斿洖涓€涓 promise 瀵硅薄锛屽彲浠ョ洃鍚 progress 杩涘害銆 * * * @method md5File * @grammar md5File( file[, start[, end]] ) => promise * @for Uploader * @example * * uploader.on( 'fileQueued', function( file ) { * var $li = ...; * * uploader.md5File( file ) * * // 鍙婃椂鏄剧ず杩涘害 * .progress(function(percentage) { * console.log('Percentage:', percentage); * }) * * // 瀹屾垚 * .then(function(val) { * console.log('md5 result:', val); * }); * * }); */ md5File: function( file, start, end ) { var md5 = new Md5(), deferred = Base.Deferred(), blob = (file instanceof Blob) ? file : this.request( 'get-file', file ).source; md5.on( 'progress load', function( e ) { e = e || {}; deferred.notify( e.total ? e.loaded / e.total : 1 ); }); md5.on( 'complete', function() { deferred.resolve( md5.getResult() ); }); md5.on( 'error', function( reason ) { deferred.reject( reason ); }); if ( arguments.length > 1 ) { start = start || 0; end = end || 0; start < 0 && (start = blob.size + start); end < 0 && (end = blob.size + end); end = Math.min( end, blob.size ); blob = blob.slice( start, end ); } md5.loadFromBlob( blob ); return deferred.promise(); } }); }); /** * @fileOverview Runtime绠$悊鍣紝璐熻矗Runtime鐨勯€夋嫨, 杩炴帴 */ define('runtime/compbase',[],function() { function CompBase( owner, runtime ) { this.owner = owner; this.options = owner.options; this.getRuntime = function() { return runtime; }; this.getRuid = function() { return runtime.uid; }; this.trigger = function() { return owner.trigger.apply( owner, arguments ); }; } return CompBase; }); /** * @fileOverview Html5Runtime */ define('runtime/html5/runtime',[ 'base', 'runtime/runtime', 'runtime/compbase' ], function( Base, Runtime, CompBase ) { var type = 'html5', components = {}; function Html5Runtime() { var pool = {}, me = this, destroy = this.destroy; Runtime.apply( me, arguments ); me.type = type; // 杩欎釜鏂规硶鐨勮皟鐢ㄨ€咃紝瀹為檯涓婃槸RuntimeClient me.exec = function( comp, fn/*, args...*/) { var client = this, uid = client.uid, args = Base.slice( arguments, 2 ), instance; if ( components[ comp ] ) { instance = pool[ uid ] = pool[ uid ] || new components[ comp ]( client, me ); if ( instance[ fn ] ) { return instance[ fn ].apply( instance, args ); } } }; me.destroy = function() { // @todo 鍒犻櫎姹犲瓙涓殑鎵€鏈夊疄渚 return destroy && destroy.apply( this, arguments ); }; } Base.inherits( Runtime, { constructor: Html5Runtime, // 涓嶉渶瑕佽繛鎺ュ叾浠栫▼搴忥紝鐩存帴鎵цcallback init: function() { var me = this; setTimeout(function() { me.trigger('ready'); }, 1 ); } }); // 娉ㄥ唽Components Html5Runtime.register = function( name, component ) { var klass = components[ name ] = Base.inherits( CompBase, component ); return klass; }; // 娉ㄥ唽html5杩愯鏃躲€ // 鍙湁鍦ㄦ敮鎸佺殑鍓嶆彁涓嬫敞鍐屻€ if ( window.Blob && window.FileReader && window.DataView ) { Runtime.addRuntime( type, Html5Runtime ); } return Html5Runtime; }); /** * @fileOverview Blob Html瀹炵幇 */ define('runtime/html5/blob',[ 'runtime/html5/runtime', 'lib/blob' ], function( Html5Runtime, Blob ) { return Html5Runtime.register( 'Blob', { slice: function( start, end ) { var blob = this.owner.source, slice = blob.slice || blob.webkitSlice || blob.mozSlice; blob = slice.call( blob, start, end ); return new Blob( this.getRuid(), blob ); } }); }); /** * @fileOverview FilePaste */ define('runtime/html5/dnd',[ 'base', 'runtime/html5/runtime', 'lib/file' ], function( Base, Html5Runtime, File ) { var $ = Base.$, prefix = 'webuploader-dnd-'; return Html5Runtime.register( 'DragAndDrop', { init: function() { var elem = this.elem = this.options.container; this.dragEnterHandler = Base.bindFn( this._dragEnterHandler, this ); this.dragOverHandler = Base.bindFn( this._dragOverHandler, this ); this.dragLeaveHandler = Base.bindFn( this._dragLeaveHandler, this ); this.dropHandler = Base.bindFn( this._dropHandler, this ); this.dndOver = false; elem.on( 'dragenter', this.dragEnterHandler ); elem.on( 'dragover', this.dragOverHandler ); elem.on( 'dragleave', this.dragLeaveHandler ); elem.on( 'drop', this.dropHandler ); if ( this.options.disableGlobalDnd ) { $( document ).on( 'dragover', this.dragOverHandler ); $( document ).on( 'drop', this.dropHandler ); } }, _dragEnterHandler: function( e ) { var me = this, denied = me._denied || false, items; e = e.originalEvent || e; if ( !me.dndOver ) { me.dndOver = true; // 娉ㄦ剰鍙湁 chrome 鏀寔銆 items = e.dataTransfer.items; if ( items && items.length ) { me._denied = denied = !me.trigger( 'accept', items ); } me.elem.addClass( prefix + 'over' ); me.elem[ denied ? 'addClass' : 'removeClass' ]( prefix + 'denied' ); } e.dataTransfer.dropEffect = denied ? 'none' : 'copy'; return false; }, _dragOverHandler: function( e ) { // 鍙鐞嗘鍐呯殑銆 var parentElem = this.elem.parent().get( 0 ); if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) { return false; } clearTimeout( this._leaveTimer ); this._dragEnterHandler.call( this, e ); return false; }, _dragLeaveHandler: function() { var me = this, handler; handler = function() { me.dndOver = false; me.elem.removeClass( prefix + 'over ' + prefix + 'denied' ); }; clearTimeout( me._leaveTimer ); me._leaveTimer = setTimeout( handler, 100 ); return false; }, _dropHandler: function( e ) { var me = this, ruid = me.getRuid(), parentElem = me.elem.parent().get( 0 ), dataTransfer, data; // 鍙鐞嗘鍐呯殑銆 if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) { return false; } e = e.originalEvent || e; dataTransfer = e.dataTransfer; // 濡傛灉鏄〉闈㈠唴鎷栨嫿锛岃繕涓嶈兘澶勭悊锛屼笉闃绘浜嬩欢銆 // 姝ゅ ie11 涓嬩細鎶ュ弬鏁伴敊璇紝 try { data = dataTransfer.getData('text/html'); } catch( err ) { } if ( data ) { return; } me._getTansferFiles( dataTransfer, function( results ) { me.trigger( 'drop', $.map( results, function( file ) { return new File( ruid, file ); }) ); }); me.dndOver = false; me.elem.removeClass( prefix + 'over' ); return false; }, // 濡傛灉浼犲叆 callback 鍒欏幓鏌ョ湅鏂囦欢澶癸紝鍚﹀垯鍙褰撳墠鏂囦欢澶广€ _getTansferFiles: function( dataTransfer, callback ) { var results = [], promises = [], items, files, file, item, i, len, canAccessFolder; items = dataTransfer.items; files = dataTransfer.files; canAccessFolder = !!(items && items[ 0 ].webkitGetAsEntry); for ( i = 0, len = files.length; i < len; i++ ) { file = files[ i ]; item = items && items[ i ]; if ( canAccessFolder && item.webkitGetAsEntry().isDirectory ) { promises.push( this._traverseDirectoryTree( item.webkitGetAsEntry(), results ) ); } else { results.push( file ); } } Base.when.apply( Base, promises ).done(function() { if ( !results.length ) { return; } callback( results ); }); }, _traverseDirectoryTree: function( entry, results ) { var deferred = Base.Deferred(), me = this; if ( entry.isFile ) { entry.file(function( file ) { results.push( file ); deferred.resolve(); }); } else if ( entry.isDirectory ) { entry.createReader().readEntries(function( entries ) { var len = entries.length, promises = [], arr = [], // 涓轰簡淇濊瘉椤哄簭銆 i; for ( i = 0; i < len; i++ ) { promises.push( me._traverseDirectoryTree( entries[ i ], arr ) ); } Base.when.apply( Base, promises ).then(function() { results.push.apply( results, arr ); deferred.resolve(); }, deferred.reject ); }); } return deferred.promise(); }, destroy: function() { var elem = this.elem; // 杩樻病 init 灏辫皟鐢 destroy if (!elem) { return; } elem.off( 'dragenter', this.dragEnterHandler ); elem.off( 'dragover', this.dragOverHandler ); elem.off( 'dragleave', this.dragLeaveHandler ); elem.off( 'drop', this.dropHandler ); if ( this.options.disableGlobalDnd ) { $( document ).off( 'dragover', this.dragOverHandler ); $( document ).off( 'drop', this.dropHandler ); } } }); }); /** * @fileOverview FilePaste */ define('runtime/html5/filepaste',[ 'base', 'runtime/html5/runtime', 'lib/file' ], function( Base, Html5Runtime, File ) { return Html5Runtime.register( 'FilePaste', { init: function() { var opts = this.options, elem = this.elem = opts.container, accept = '.*', arr, i, len, item; // accetp鐨刴imeTypes涓敓鎴愬尮閰嶆鍒欍€ if ( opts.accept ) { arr = []; for ( i = 0, len = opts.accept.length; i < len; i++ ) { item = opts.accept[ i ].mimeTypes; item && arr.push( item ); } if ( arr.length ) { accept = arr.join(','); accept = accept.replace( /,/g, '|' ).replace( /\*/g, '.*' ); } } this.accept = accept = new RegExp( accept, 'i' ); this.hander = Base.bindFn( this._pasteHander, this ); elem.on( 'paste', this.hander ); }, _pasteHander: function( e ) { var allowed = [], ruid = this.getRuid(), items, item, blob, i, len; e = e.originalEvent || e; items = e.clipboardData.items; for ( i = 0, len = items.length; i < len; i++ ) { item = items[ i ]; if ( item.kind !== 'file' || !(blob = item.getAsFile()) ) { continue; } allowed.push( new File( ruid, blob ) ); } if ( allowed.length ) { // 涓嶉樆姝㈤潪鏂囦欢绮樿创锛堟枃瀛楃矘璐达級鐨勪簨浠跺啋娉 e.preventDefault(); e.stopPropagation(); this.trigger( 'paste', allowed ); } }, destroy: function() { this.elem.off( 'paste', this.hander ); } }); }); /** * @fileOverview FilePicker */ define('runtime/html5/filepicker',[ 'base', 'runtime/html5/runtime' ], function( Base, Html5Runtime ) { var $ = Base.$; return Html5Runtime.register( 'FilePicker', { init: function() { var container = this.getRuntime().getContainer(), me = this, owner = me.owner, opts = me.options, label = this.label = $( document.createElement('label') ), input = this.input = $( document.createElement('input') ), arr, i, len, mouseHandler; input.attr( 'type', 'file' ); input.attr( 'name', opts.name ); input.addClass('webuploader-element-invisible'); label.on( 'click', function() { input.trigger('click'); }); label.css({ opacity: 0, width: '100%', height: '100%', display: 'block', cursor: 'pointer', background: '#ffffff' }); if ( opts.multiple ) { input.attr( 'multiple', 'multiple' ); } // @todo Firefox涓嶆敮鎸佸崟鐙寚瀹氬悗缂€ if ( opts.accept && opts.accept.length > 0 ) { arr = []; for ( i = 0, len = opts.accept.length; i < len; i++ ) { arr.push( opts.accept[ i ].mimeTypes ); } input.attr( 'accept', arr.join(',') ); } container.append( input ); container.append( label ); mouseHandler = function( e ) { owner.trigger( e.type ); }; input.on( 'change', function( e ) { var fn = arguments.callee, clone; me.files = e.target.files; // reset input clone = this.cloneNode( true ); clone.value = null; this.parentNode.replaceChild( clone, this ); input.off(); input = $( clone ).on( 'change', fn ) .on( 'mouseenter mouseleave', mouseHandler ); owner.trigger('change'); }); label.on( 'mouseenter mouseleave', mouseHandler ); }, getFiles: function() { return this.files; }, destroy: function() { this.input.off(); this.label.off(); } }); }); /** * Terms: * * Uint8Array, FileReader, BlobBuilder, atob, ArrayBuffer * @fileOverview Image鎺т欢 */ define('runtime/html5/util',[ 'base' ], function( Base ) { var urlAPI = window.createObjectURL && window || window.URL && URL.revokeObjectURL && URL || window.webkitURL, createObjectURL = Base.noop, revokeObjectURL = createObjectURL; if ( urlAPI ) { // 鏇村畨鍏ㄧ殑鏂瑰紡璋冪敤锛屾瘮濡俛ndroid閲岄潰灏辫兘鎶奵ontext鏀规垚鍏朵粬鐨勫璞°€ createObjectURL = function() { return urlAPI.createObjectURL.apply( urlAPI, arguments ); }; revokeObjectURL = function() { return urlAPI.revokeObjectURL.apply( urlAPI, arguments ); }; } return { createObjectURL: createObjectURL, revokeObjectURL: revokeObjectURL, dataURL2Blob: function( dataURI ) { var byteStr, intArray, ab, i, mimetype, parts; parts = dataURI.split(','); if ( ~parts[ 0 ].indexOf('base64') ) { byteStr = atob( parts[ 1 ] ); } else { byteStr = decodeURIComponent( parts[ 1 ] ); } ab = new ArrayBuffer( byteStr.length ); intArray = new Uint8Array( ab ); for ( i = 0; i < byteStr.length; i++ ) { intArray[ i ] = byteStr.charCodeAt( i ); } mimetype = parts[ 0 ].split(':')[ 1 ].split(';')[ 0 ]; return this.arrayBufferToBlob( ab, mimetype ); }, dataURL2ArrayBuffer: function( dataURI ) { var byteStr, intArray, i, parts; parts = dataURI.split(','); if ( ~parts[ 0 ].indexOf('base64') ) { byteStr = atob( parts[ 1 ] ); } else { byteStr = decodeURIComponent( parts[ 1 ] ); } intArray = new Uint8Array( byteStr.length ); for ( i = 0; i < byteStr.length; i++ ) { intArray[ i ] = byteStr.charCodeAt( i ); } return intArray.buffer; }, arrayBufferToBlob: function( buffer, type ) { var builder = window.BlobBuilder || window.WebKitBlobBuilder, bb; // android涓嶆敮鎸佺洿鎺ew Blob, 鍙兘鍊熷姪blobbuilder. if ( builder ) { bb = new builder(); bb.append( buffer ); return bb.getBlob( type ); } return new Blob([ buffer ], type ? { type: type } : {} ); }, // 鎶藉嚭鏉ヤ富瑕佹槸涓轰簡瑙e喅android涓嬮潰canvas.toDataUrl涓嶆敮鎸乯peg. // 浣犲緱鍒扮殑缁撴灉鏄痯ng. canvasToDataUrl: function( canvas, type, quality ) { return canvas.toDataURL( type, quality / 100 ); }, // imagemeat浼氬鍐欒繖涓柟娉曪紝濡傛灉鐢ㄦ埛閫夋嫨鍔犺浇閭d釜鏂囦欢浜嗙殑璇濄€ parseMeta: function( blob, callback ) { callback( false, {}); }, // imagemeat浼氬鍐欒繖涓柟娉曪紝濡傛灉鐢ㄦ埛閫夋嫨鍔犺浇閭d釜鏂囦欢浜嗙殑璇濄€ updateImageHead: function( data ) { return data; } }; }); /** * Terms: * * Uint8Array, FileReader, BlobBuilder, atob, ArrayBuffer * @fileOverview Image鎺т欢 */ define('runtime/html5/imagemeta',[ 'runtime/html5/util' ], function( Util ) { var api; api = { parsers: { 0xffe1: [] }, maxMetaDataSize: 262144, parse: function( blob, cb ) { var me = this, fr = new FileReader(); fr.onload = function() { cb( false, me._parse( this.result ) ); fr = fr.onload = fr.onerror = null; }; fr.onerror = function( e ) { cb( e.message ); fr = fr.onload = fr.onerror = null; }; blob = blob.slice( 0, me.maxMetaDataSize ); fr.readAsArrayBuffer( blob.getSource() ); }, _parse: function( buffer, noParse ) { if ( buffer.byteLength < 6 ) { return; } var dataview = new DataView( buffer ), offset = 2, maxOffset = dataview.byteLength - 4, headLength = offset, ret = {}, markerBytes, markerLength, parsers, i; if ( dataview.getUint16( 0 ) === 0xffd8 ) { while ( offset < maxOffset ) { markerBytes = dataview.getUint16( offset ); if ( markerBytes >= 0xffe0 && markerBytes <= 0xffef || markerBytes === 0xfffe ) { markerLength = dataview.getUint16( offset + 2 ) + 2; if ( offset + markerLength > dataview.byteLength ) { break; } parsers = api.parsers[ markerBytes ]; if ( !noParse && parsers ) { for ( i = 0; i < parsers.length; i += 1 ) { parsers[ i ].call( api, dataview, offset, markerLength, ret ); } } offset += markerLength; headLength = offset; } else { break; } } if ( headLength > 6 ) { if ( buffer.slice ) { ret.imageHead = buffer.slice( 2, headLength ); } else { // Workaround for IE10, which does not yet // support ArrayBuffer.slice: ret.imageHead = new Uint8Array( buffer ) .subarray( 2, headLength ); } } } return ret; }, updateImageHead: function( buffer, head ) { var data = this._parse( buffer, true ), buf1, buf2, bodyoffset; bodyoffset = 2; if ( data.imageHead ) { bodyoffset = 2 + data.imageHead.byteLength; } if ( buffer.slice ) { buf2 = buffer.slice( bodyoffset ); } else { buf2 = new Uint8Array( buffer ).subarray( bodyoffset ); } buf1 = new Uint8Array( head.byteLength + 2 + buf2.byteLength ); buf1[ 0 ] = 0xFF; buf1[ 1 ] = 0xD8; buf1.set( new Uint8Array( head ), 2 ); buf1.set( new Uint8Array( buf2 ), head.byteLength + 2 ); return buf1.buffer; } }; Util.parseMeta = function() { return api.parse.apply( api, arguments ); }; Util.updateImageHead = function() { return api.updateImageHead.apply( api, arguments ); }; return api; }); /** * 浠g爜鏉ヨ嚜浜庯細https://github.com/blueimp/JavaScript-Load-Image * 鏆傛椂椤圭洰涓彧鐢ㄤ簡orientation. * * 鍘婚櫎浜 Exif Sub IFD Pointer, GPS Info IFD Pointer, Exif Thumbnail. * @fileOverview EXIF瑙f瀽 */ // Sample // ==================================== // Make : Apple // Model : iPhone 4S // Orientation : 1 // XResolution : 72 [72/1] // YResolution : 72 [72/1] // ResolutionUnit : 2 // Software : QuickTime 7.7.1 // DateTime : 2013:09:01 22:53:55 // ExifIFDPointer : 190 // ExposureTime : 0.058823529411764705 [1/17] // FNumber : 2.4 [12/5] // ExposureProgram : Normal program // ISOSpeedRatings : 800 // ExifVersion : 0220 // DateTimeOriginal : 2013:09:01 22:52:51 // DateTimeDigitized : 2013:09:01 22:52:51 // ComponentsConfiguration : YCbCr // ShutterSpeedValue : 4.058893515764426 // ApertureValue : 2.5260688216892597 [4845/1918] // BrightnessValue : -0.3126686601998395 // MeteringMode : Pattern // Flash : Flash did not fire, compulsory flash mode // FocalLength : 4.28 [107/25] // SubjectArea : [4 values] // FlashpixVersion : 0100 // ColorSpace : 1 // PixelXDimension : 2448 // PixelYDimension : 3264 // SensingMethod : One-chip color area sensor // ExposureMode : 0 // WhiteBalance : Auto white balance // FocalLengthIn35mmFilm : 35 // SceneCaptureType : Standard define('runtime/html5/imagemeta/exif',[ 'base', 'runtime/html5/imagemeta' ], function( Base, ImageMeta ) { var EXIF = {}; EXIF.ExifMap = function() { return this; }; EXIF.ExifMap.prototype.map = { 'Orientation': 0x0112 }; EXIF.ExifMap.prototype.get = function( id ) { return this[ id ] || this[ this.map[ id ] ]; }; EXIF.exifTagTypes = { // byte, 8-bit unsigned int: 1: { getValue: function( dataView, dataOffset ) { return dataView.getUint8( dataOffset ); }, size: 1 }, // ascii, 8-bit byte: 2: { getValue: function( dataView, dataOffset ) { return String.fromCharCode( dataView.getUint8( dataOffset ) ); }, size: 1, ascii: true }, // short, 16 bit int: 3: { getValue: function( dataView, dataOffset, littleEndian ) { return dataView.getUint16( dataOffset, littleEndian ); }, size: 2 }, // long, 32 bit int: 4: { getValue: function( dataView, dataOffset, littleEndian ) { return dataView.getUint32( dataOffset, littleEndian ); }, size: 4 }, // rational = two long values, // first is numerator, second is denominator: 5: { getValue: function( dataView, dataOffset, littleEndian ) { return dataView.getUint32( dataOffset, littleEndian ) / dataView.getUint32( dataOffset + 4, littleEndian ); }, size: 8 }, // slong, 32 bit signed int: 9: { getValue: function( dataView, dataOffset, littleEndian ) { return dataView.getInt32( dataOffset, littleEndian ); }, size: 4 }, // srational, two slongs, first is numerator, second is denominator: 10: { getValue: function( dataView, dataOffset, littleEndian ) { return dataView.getInt32( dataOffset, littleEndian ) / dataView.getInt32( dataOffset + 4, littleEndian ); }, size: 8 } }; // undefined, 8-bit byte, value depending on field: EXIF.exifTagTypes[ 7 ] = EXIF.exifTagTypes[ 1 ]; EXIF.getExifValue = function( dataView, tiffOffset, offset, type, length, littleEndian ) { var tagType = EXIF.exifTagTypes[ type ], tagSize, dataOffset, values, i, str, c; if ( !tagType ) { Base.log('Invalid Exif data: Invalid tag type.'); return; } tagSize = tagType.size * length; // Determine if the value is contained in the dataOffset bytes, // or if the value at the dataOffset is a pointer to the actual data: dataOffset = tagSize > 4 ? tiffOffset + dataView.getUint32( offset + 8, littleEndian ) : (offset + 8); if ( dataOffset + tagSize > dataView.byteLength ) { Base.log('Invalid Exif data: Invalid data offset.'); return; } if ( length === 1 ) { return tagType.getValue( dataView, dataOffset, littleEndian ); } values = []; for ( i = 0; i < length; i += 1 ) { values[ i ] = tagType.getValue( dataView, dataOffset + i * tagType.size, littleEndian ); } if ( tagType.ascii ) { str = ''; // Concatenate the chars: for ( i = 0; i < values.length; i += 1 ) { c = values[ i ]; // Ignore the terminating NULL byte(s): if ( c === '\u0000' ) { break; } str += c; } return str; } return values; }; EXIF.parseExifTag = function( dataView, tiffOffset, offset, littleEndian, data ) { var tag = dataView.getUint16( offset, littleEndian ); data.exif[ tag ] = EXIF.getExifValue( dataView, tiffOffset, offset, dataView.getUint16( offset + 2, littleEndian ), // tag type dataView.getUint32( offset + 4, littleEndian ), // tag length littleEndian ); }; EXIF.parseExifTags = function( dataView, tiffOffset, dirOffset, littleEndian, data ) { var tagsNumber, dirEndOffset, i; if ( dirOffset + 6 > dataView.byteLength ) { Base.log('Invalid Exif data: Invalid directory offset.'); return; } tagsNumber = dataView.getUint16( dirOffset, littleEndian ); dirEndOffset = dirOffset + 2 + 12 * tagsNumber; if ( dirEndOffset + 4 > dataView.byteLength ) { Base.log('Invalid Exif data: Invalid directory size.'); return; } for ( i = 0; i < tagsNumber; i += 1 ) { this.parseExifTag( dataView, tiffOffset, dirOffset + 2 + 12 * i, // tag offset littleEndian, data ); } // Return the offset to the next directory: return dataView.getUint32( dirEndOffset, littleEndian ); }; // EXIF.getExifThumbnail = function(dataView, offset, length) { // var hexData, // i, // b; // if (!length || offset + length > dataView.byteLength) { // Base.log('Invalid Exif data: Invalid thumbnail data.'); // return; // } // hexData = []; // for (i = 0; i < length; i += 1) { // b = dataView.getUint8(offset + i); // hexData.push((b < 16 ? '0' : '') + b.toString(16)); // } // return 'data:image/jpeg,%' + hexData.join('%'); // }; EXIF.parseExifData = function( dataView, offset, length, data ) { var tiffOffset = offset + 10, littleEndian, dirOffset; // Check for the ASCII code for "Exif" (0x45786966): if ( dataView.getUint32( offset + 4 ) !== 0x45786966 ) { // No Exif data, might be XMP data instead return; } if ( tiffOffset + 8 > dataView.byteLength ) { Base.log('Invalid Exif data: Invalid segment size.'); return; } // Check for the two null bytes: if ( dataView.getUint16( offset + 8 ) !== 0x0000 ) { Base.log('Invalid Exif data: Missing byte alignment offset.'); return; } // Check the byte alignment: switch ( dataView.getUint16( tiffOffset ) ) { case 0x4949: littleEndian = true; break; case 0x4D4D: littleEndian = false; break; default: Base.log('Invalid Exif data: Invalid byte alignment marker.'); return; } // Check for the TIFF tag marker (0x002A): if ( dataView.getUint16( tiffOffset + 2, littleEndian ) !== 0x002A ) { Base.log('Invalid Exif data: Missing TIFF marker.'); return; } // Retrieve the directory offset bytes, usually 0x00000008 or 8 decimal: dirOffset = dataView.getUint32( tiffOffset + 4, littleEndian ); // Create the exif object to store the tags: data.exif = new EXIF.ExifMap(); // Parse the tags of the main image directory and retrieve the // offset to the next directory, usually the thumbnail directory: dirOffset = EXIF.parseExifTags( dataView, tiffOffset, tiffOffset + dirOffset, littleEndian, data ); // 灏濊瘯璇诲彇缂╃暐鍥 // if ( dirOffset ) { // thumbnailData = {exif: {}}; // dirOffset = EXIF.parseExifTags( // dataView, // tiffOffset, // tiffOffset + dirOffset, // littleEndian, // thumbnailData // ); // // Check for JPEG Thumbnail offset: // if (thumbnailData.exif[0x0201]) { // data.exif.Thumbnail = EXIF.getExifThumbnail( // dataView, // tiffOffset + thumbnailData.exif[0x0201], // thumbnailData.exif[0x0202] // Thumbnail data length // ); // } // } }; ImageMeta.parsers[ 0xffe1 ].push( EXIF.parseExifData ); return EXIF; }); /** * 杩欎釜鏂瑰紡鎬ц兘涓嶈锛屼絾鏄彲浠ヨВ鍐砤ndroid閲岄潰鐨則oDataUrl鐨刡ug * android閲岄潰toDataUrl('image/jpege')寰楀埌鐨勭粨鏋滃嵈鏄痯ng. * * 鎵€浠ヨ繖閲屾病杈欙紝鍙兘鍊熷姪杩欎釜宸ュ叿 * @fileOverview jpeg encoder */ define('runtime/html5/jpegencoder',[], function( require, exports, module ) { /* Copyright (c) 2008, Adobe Systems Incorporated All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Adobe Systems Incorporated nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* JPEG encoder ported to JavaScript and optimized by Andreas Ritter, www.bytestrom.eu, 11/2009 Basic GUI blocking jpeg encoder */ function JPEGEncoder(quality) { var self = this; var fround = Math.round; var ffloor = Math.floor; var YTable = new Array(64); var UVTable = new Array(64); var fdtbl_Y = new Array(64); var fdtbl_UV = new Array(64); var YDC_HT; var UVDC_HT; var YAC_HT; var UVAC_HT; var bitcode = new Array(65535); var category = new Array(65535); var outputfDCTQuant = new Array(64); var DU = new Array(64); var byteout = []; var bytenew = 0; var bytepos = 7; var YDU = new Array(64); var UDU = new Array(64); var VDU = new Array(64); var clt = new Array(256); var RGB_YUV_TABLE = new Array(2048); var currentQuality; var ZigZag = [ 0, 1, 5, 6,14,15,27,28, 2, 4, 7,13,16,26,29,42, 3, 8,12,17,25,30,41,43, 9,11,18,24,31,40,44,53, 10,19,23,32,39,45,52,54, 20,22,33,38,46,51,55,60, 21,34,37,47,50,56,59,61, 35,36,48,49,57,58,62,63 ]; var std_dc_luminance_nrcodes = [0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0]; var std_dc_luminance_values = [0,1,2,3,4,5,6,7,8,9,10,11]; var std_ac_luminance_nrcodes = [0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d]; var std_ac_luminance_values = [ 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12, 0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07, 0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08, 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0, 0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16, 0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28, 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39, 0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49, 0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59, 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69, 0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79, 0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89, 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98, 0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7, 0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6, 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5, 0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4, 0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2, 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea, 0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8, 0xf9,0xfa ]; var std_dc_chrominance_nrcodes = [0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0]; var std_dc_chrominance_values = [0,1,2,3,4,5,6,7,8,9,10,11]; var std_ac_chrominance_nrcodes = [0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77]; var std_ac_chrominance_values = [ 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21, 0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71, 0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91, 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0, 0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34, 0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26, 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38, 0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48, 0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58, 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68, 0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78, 0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96, 0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5, 0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4, 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3, 0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2, 0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda, 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9, 0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8, 0xf9,0xfa ]; function initQuantTables(sf){ var YQT = [ 16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60, 55, 14, 13, 16, 24, 40, 57, 69, 56, 14, 17, 22, 29, 51, 87, 80, 62, 18, 22, 37, 56, 68,109,103, 77, 24, 35, 55, 64, 81,104,113, 92, 49, 64, 78, 87,103,121,120,101, 72, 92, 95, 98,112,100,103, 99 ]; for (var i = 0; i < 64; i++) { var t = ffloor((YQT[i]*sf+50)/100); if (t < 1) { t = 1; } else if (t > 255) { t = 255; } YTable[ZigZag[i]] = t; } var UVQT = [ 17, 18, 24, 47, 99, 99, 99, 99, 18, 21, 26, 66, 99, 99, 99, 99, 24, 26, 56, 99, 99, 99, 99, 99, 47, 66, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99 ]; for (var j = 0; j < 64; j++) { var u = ffloor((UVQT[j]*sf+50)/100); if (u < 1) { u = 1; } else if (u > 255) { u = 255; } UVTable[ZigZag[j]] = u; } var aasf = [ 1.0, 1.387039845, 1.306562965, 1.175875602, 1.0, 0.785694958, 0.541196100, 0.275899379 ]; var k = 0; for (var row = 0; row < 8; row++) { for (var col = 0; col < 8; col++) { fdtbl_Y[k] = (1.0 / (YTable [ZigZag[k]] * aasf[row] * aasf[col] * 8.0)); fdtbl_UV[k] = (1.0 / (UVTable[ZigZag[k]] * aasf[row] * aasf[col] * 8.0)); k++; } } } function computeHuffmanTbl(nrcodes, std_table){ var codevalue = 0; var pos_in_table = 0; var HT = new Array(); for (var k = 1; k <= 16; k++) { for (var j = 1; j <= nrcodes[k]; j++) { HT[std_table[pos_in_table]] = []; HT[std_table[pos_in_table]][0] = codevalue; HT[std_table[pos_in_table]][1] = k; pos_in_table++; codevalue++; } codevalue*=2; } return HT; } function initHuffmanTbl() { YDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes,std_dc_luminance_values); UVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes,std_dc_chrominance_values); YAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes,std_ac_luminance_values); UVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes,std_ac_chrominance_values); } function initCategoryNumber() { var nrlower = 1; var nrupper = 2; for (var cat = 1; cat <= 15; cat++) { //Positive numbers for (var nr = nrlower; nr>0] = 38470 * i; RGB_YUV_TABLE[(i+ 512)>>0] = 7471 * i + 0x8000; RGB_YUV_TABLE[(i+ 768)>>0] = -11059 * i; RGB_YUV_TABLE[(i+1024)>>0] = -21709 * i; RGB_YUV_TABLE[(i+1280)>>0] = 32768 * i + 0x807FFF; RGB_YUV_TABLE[(i+1536)>>0] = -27439 * i; RGB_YUV_TABLE[(i+1792)>>0] = - 5329 * i; } } // IO functions function writeBits(bs) { var value = bs[0]; var posval = bs[1]-1; while ( posval >= 0 ) { if (value & (1 << posval) ) { bytenew |= (1 << bytepos); } posval--; bytepos--; if (bytepos < 0) { if (bytenew == 0xFF) { writeByte(0xFF); writeByte(0); } else { writeByte(bytenew); } bytepos=7; bytenew=0; } } } function writeByte(value) { byteout.push(clt[value]); // write char directly instead of converting later } function writeWord(value) { writeByte((value>>8)&0xFF); writeByte((value )&0xFF); } // DCT & quantization core function fDCTQuant(data, fdtbl) { var d0, d1, d2, d3, d4, d5, d6, d7; /* Pass 1: process rows. */ var dataOff=0; var i; var I8 = 8; var I64 = 64; for (i=0; i 0.0) ? ((fDCTQuant + 0.5)|0) : ((fDCTQuant - 0.5)|0); //outputfDCTQuant[i] = fround(fDCTQuant); } return outputfDCTQuant; } function writeAPP0() { writeWord(0xFFE0); // marker writeWord(16); // length writeByte(0x4A); // J writeByte(0x46); // F writeByte(0x49); // I writeByte(0x46); // F writeByte(0); // = "JFIF",'\0' writeByte(1); // versionhi writeByte(1); // versionlo writeByte(0); // xyunits writeWord(1); // xdensity writeWord(1); // ydensity writeByte(0); // thumbnwidth writeByte(0); // thumbnheight } function writeSOF0(width, height) { writeWord(0xFFC0); // marker writeWord(17); // length, truecolor YUV JPG writeByte(8); // precision writeWord(height); writeWord(width); writeByte(3); // nrofcomponents writeByte(1); // IdY writeByte(0x11); // HVY writeByte(0); // QTY writeByte(2); // IdU writeByte(0x11); // HVU writeByte(1); // QTU writeByte(3); // IdV writeByte(0x11); // HVV writeByte(1); // QTV } function writeDQT() { writeWord(0xFFDB); // marker writeWord(132); // length writeByte(0); for (var i=0; i<64; i++) { writeByte(YTable[i]); } writeByte(1); for (var j=0; j<64; j++) { writeByte(UVTable[j]); } } function writeDHT() { writeWord(0xFFC4); // marker writeWord(0x01A2); // length writeByte(0); // HTYDCinfo for (var i=0; i<16; i++) { writeByte(std_dc_luminance_nrcodes[i+1]); } for (var j=0; j<=11; j++) { writeByte(std_dc_luminance_values[j]); } writeByte(0x10); // HTYACinfo for (var k=0; k<16; k++) { writeByte(std_ac_luminance_nrcodes[k+1]); } for (var l=0; l<=161; l++) { writeByte(std_ac_luminance_values[l]); } writeByte(1); // HTUDCinfo for (var m=0; m<16; m++) { writeByte(std_dc_chrominance_nrcodes[m+1]); } for (var n=0; n<=11; n++) { writeByte(std_dc_chrominance_values[n]); } writeByte(0x11); // HTUACinfo for (var o=0; o<16; o++) { writeByte(std_ac_chrominance_nrcodes[o+1]); } for (var p=0; p<=161; p++) { writeByte(std_ac_chrominance_values[p]); } } function writeSOS() { writeWord(0xFFDA); // marker writeWord(12); // length writeByte(3); // nrofcomponents writeByte(1); // IdY writeByte(0); // HTY writeByte(2); // IdU writeByte(0x11); // HTU writeByte(3); // IdV writeByte(0x11); // HTV writeByte(0); // Ss writeByte(0x3f); // Se writeByte(0); // Bf } function processDU(CDU, fdtbl, DC, HTDC, HTAC){ var EOB = HTAC[0x00]; var M16zeroes = HTAC[0xF0]; var pos; var I16 = 16; var I63 = 63; var I64 = 64; var DU_DCT = fDCTQuant(CDU, fdtbl); //ZigZag reorder for (var j=0;j0)&&(DU[end0pos]==0); end0pos--) {}; //end0pos = first element in reverse order !=0 if ( end0pos == 0) { writeBits(EOB); return DC; } var i = 1; var lng; while ( i <= end0pos ) { var startpos = i; for (; (DU[i]==0) && (i<=end0pos); ++i) {} var nrzeroes = i-startpos; if ( nrzeroes >= I16 ) { lng = nrzeroes>>4; for (var nrmarker=1; nrmarker <= lng; ++nrmarker) writeBits(M16zeroes); nrzeroes = nrzeroes&0xF; } pos = 32767+DU[i]; writeBits(HTAC[(nrzeroes<<4)+category[pos]]); writeBits(bitcode[pos]); i++; } if ( end0pos != I63 ) { writeBits(EOB); } return DC; } function initCharLookupTable(){ var sfcc = String.fromCharCode; for(var i=0; i < 256; i++){ ///// ACHTUNG // 255 clt[i] = sfcc(i); } } this.encode = function(image,quality) // image data object { // var time_start = new Date().getTime(); if(quality) setQuality(quality); // Initialize bit writer byteout = new Array(); bytenew=0; bytepos=7; // Add JPEG headers writeWord(0xFFD8); // SOI writeAPP0(); writeDQT(); writeSOF0(image.width,image.height); writeDHT(); writeSOS(); // Encode 8x8 macroblocks var DCY=0; var DCU=0; var DCV=0; bytenew=0; bytepos=7; this.encode.displayName = "_encode_"; var imageData = image.data; var width = image.width; var height = image.height; var quadWidth = width*4; var tripleWidth = width*3; var x, y = 0; var r, g, b; var start,p, col,row,pos; while(y < height){ x = 0; while(x < quadWidth){ start = quadWidth * y + x; p = start; col = -1; row = 0; for(pos=0; pos < 64; pos++){ row = pos >> 3;// /8 col = ( pos & 7 ) * 4; // %8 p = start + ( row * quadWidth ) + col; if(y+row >= height){ // padding bottom p-= (quadWidth*(y+1+row-height)); } if(x+col >= quadWidth){ // padding right p-= ((x+col) - quadWidth +4) } r = imageData[ p++ ]; g = imageData[ p++ ]; b = imageData[ p++ ]; /* // calculate YUV values dynamically YDU[pos]=((( 0.29900)*r+( 0.58700)*g+( 0.11400)*b))-128; //-0x80 UDU[pos]=(((-0.16874)*r+(-0.33126)*g+( 0.50000)*b)); VDU[pos]=((( 0.50000)*r+(-0.41869)*g+(-0.08131)*b)); */ // use lookup table (slightly faster) YDU[pos] = ((RGB_YUV_TABLE[r] + RGB_YUV_TABLE[(g + 256)>>0] + RGB_YUV_TABLE[(b + 512)>>0]) >> 16)-128; UDU[pos] = ((RGB_YUV_TABLE[(r + 768)>>0] + RGB_YUV_TABLE[(g + 1024)>>0] + RGB_YUV_TABLE[(b + 1280)>>0]) >> 16)-128; VDU[pos] = ((RGB_YUV_TABLE[(r + 1280)>>0] + RGB_YUV_TABLE[(g + 1536)>>0] + RGB_YUV_TABLE[(b + 1792)>>0]) >> 16)-128; } DCY = processDU(YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT); DCU = processDU(UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT); DCV = processDU(VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT); x+=32; } y+=8; } //////////////////////////////////////////////////////////////// // Do the bit alignment of the EOI marker if ( bytepos >= 0 ) { var fillbits = []; fillbits[1] = bytepos+1; fillbits[0] = (1<<(bytepos+1))-1; writeBits(fillbits); } writeWord(0xFFD9); //EOI var jpegDataUri = 'data:image/jpeg;base64,' + btoa(byteout.join('')); byteout = []; // benchmarking // var duration = new Date().getTime() - time_start; // console.log('Encoding time: '+ currentQuality + 'ms'); // return jpegDataUri } function setQuality(quality){ if (quality <= 0) { quality = 1; } if (quality > 100) { quality = 100; } if(currentQuality == quality) return // don't recalc if unchanged var sf = 0; if (quality < 50) { sf = Math.floor(5000 / quality); } else { sf = Math.floor(200 - quality*2); } initQuantTables(sf); currentQuality = quality; // console.log('Quality set to: '+quality +'%'); } function init(){ // var time_start = new Date().getTime(); if(!quality) quality = 50; // Create tables initCharLookupTable() initHuffmanTbl(); initCategoryNumber(); initRGBYUVTable(); setQuality(quality); // var duration = new Date().getTime() - time_start; // console.log('Initialization '+ duration + 'ms'); } init(); }; JPEGEncoder.encode = function( data, quality ) { var encoder = new JPEGEncoder( quality ); return encoder.encode( data ); } return JPEGEncoder; }); /** * @fileOverview Fix android canvas.toDataUrl bug. */ define('runtime/html5/androidpatch',[ 'runtime/html5/util', 'runtime/html5/jpegencoder', 'base' ], function( Util, encoder, Base ) { var origin = Util.canvasToDataUrl, supportJpeg; Util.canvasToDataUrl = function( canvas, type, quality ) { var ctx, w, h, fragement, parts; // 闈瀉ndroid鎵嬫満鐩存帴璺宠繃銆 if ( !Base.os.android ) { return origin.apply( null, arguments ); } // 妫€娴嬫槸鍚anvas鏀寔jpeg瀵煎嚭锛屾牴鎹暟鎹牸寮忔潵鍒ゆ柇銆 // JPEG 鍓嶄袱浣嶅垎鍒槸锛?55, 216 if ( type === 'image/jpeg' && typeof supportJpeg === 'undefined' ) { fragement = origin.apply( null, arguments ); parts = fragement.split(','); if ( ~parts[ 0 ].indexOf('base64') ) { fragement = atob( parts[ 1 ] ); } else { fragement = decodeURIComponent( parts[ 1 ] ); } fragement = fragement.substring( 0, 2 ); supportJpeg = fragement.charCodeAt( 0 ) === 255 && fragement.charCodeAt( 1 ) === 216; } // 鍙湁鍦╝ndroid鐜涓嬫墠淇 if ( type === 'image/jpeg' && !supportJpeg ) { w = canvas.width; h = canvas.height; ctx = canvas.getContext('2d'); return encoder.encode( ctx.getImageData( 0, 0, w, h ), quality ); } return origin.apply( null, arguments ); }; }); /** * @fileOverview Image */ define('runtime/html5/image',[ 'base', 'runtime/html5/runtime', 'runtime/html5/util' ], function( Base, Html5Runtime, Util ) { var BLANK = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D'; return Html5Runtime.register( 'Image', { // flag: 鏍囪鏄惁琚慨鏀硅繃銆 modified: false, init: function() { var me = this, img = new Image(); img.onload = function() { me._info = { type: me.type, width: this.width, height: this.height }; // 璇诲彇meta淇℃伅銆 if ( !me._metas && 'image/jpeg' === me.type ) { Util.parseMeta( me._blob, function( error, ret ) { me._metas = ret; me.owner.trigger('load'); }); } else { me.owner.trigger('load'); } }; img.onerror = function() { me.owner.trigger('error'); }; me._img = img; }, loadFromBlob: function( blob ) { var me = this, img = me._img; me._blob = blob; me.type = blob.type; img.src = Util.createObjectURL( blob.getSource() ); me.owner.once( 'load', function() { Util.revokeObjectURL( img.src ); }); }, resize: function( width, height ) { var canvas = this._canvas || (this._canvas = document.createElement('canvas')); this._resize( this._img, canvas, width, height ); this._blob = null; // 娌$敤浜嗭紝鍙互鍒犳帀浜嗐€ this.modified = true; this.owner.trigger( 'complete', 'resize' ); }, crop: function( x, y, w, h, s ) { var cvs = this._canvas || (this._canvas = document.createElement('canvas')), opts = this.options, img = this._img, iw = img.naturalWidth, ih = img.naturalHeight, orientation = this.getOrientation(); s = s || 1; // todo 瑙e喅 orientation 鐨勯棶棰樸€ // values that require 90 degree rotation // if ( ~[ 5, 6, 7, 8 ].indexOf( orientation ) ) { // switch ( orientation ) { // case 6: // tmp = x; // x = y; // y = iw * s - tmp - w; // console.log(ih * s, tmp, w) // break; // } // (w ^= h, h ^= w, w ^= h); // } cvs.width = w; cvs.height = h; opts.preserveHeaders || this._rotate2Orientaion( cvs, orientation ); this._renderImageToCanvas( cvs, img, -x, -y, iw * s, ih * s ); this._blob = null; // 娌$敤浜嗭紝鍙互鍒犳帀浜嗐€ this.modified = true; this.owner.trigger( 'complete', 'crop' ); }, getAsBlob: function( type ) { var blob = this._blob, opts = this.options, canvas; type = type || this.type; // blob闇€瑕侀噸鏂扮敓鎴愩€ if ( this.modified || this.type !== type ) { canvas = this._canvas; if ( type === 'image/jpeg' ) { blob = Util.canvasToDataUrl( canvas, type, opts.quality ); if ( opts.preserveHeaders && this._metas && this._metas.imageHead ) { blob = Util.dataURL2ArrayBuffer( blob ); blob = Util.updateImageHead( blob, this._metas.imageHead ); blob = Util.arrayBufferToBlob( blob, type ); return blob; } } else { blob = Util.canvasToDataUrl( canvas, type ); } blob = Util.dataURL2Blob( blob ); } return blob; }, getAsDataUrl: function( type ) { var opts = this.options; type = type || this.type; if ( type === 'image/jpeg' ) { return Util.canvasToDataUrl( this._canvas, type, opts.quality ); } else { return this._canvas.toDataURL( type ); } }, getOrientation: function() { return this._metas && this._metas.exif && this._metas.exif.get('Orientation') || 1; }, info: function( val ) { // setter if ( val ) { this._info = val; return this; } // getter return this._info; }, meta: function( val ) { // setter if ( val ) { this._meta = val; return this; } // getter return this._meta; }, destroy: function() { var canvas = this._canvas; this._img.onload = null; if ( canvas ) { canvas.getContext('2d') .clearRect( 0, 0, canvas.width, canvas.height ); canvas.width = canvas.height = 0; this._canvas = null; } // 閲婃斁鍐呭瓨銆傞潪甯搁噸瑕侊紝鍚﹀垯閲婃斁涓嶄簡image鐨勫唴瀛樸€ this._img.src = BLANK; this._img = this._blob = null; }, _resize: function( img, cvs, width, height ) { var opts = this.options, naturalWidth = img.width, naturalHeight = img.height, orientation = this.getOrientation(), scale, w, h, x, y; // values that require 90 degree rotation if ( ~[ 5, 6, 7, 8 ].indexOf( orientation ) ) { // 浜ゆ崲width, height鐨勫€笺€ width ^= height; height ^= width; width ^= height; } scale = Math[ opts.crop ? 'max' : 'min' ]( width / naturalWidth, height / naturalHeight ); // 涓嶅厑璁告斁澶с€ opts.allowMagnify || (scale = Math.min( 1, scale )); w = naturalWidth * scale; h = naturalHeight * scale; if ( opts.crop ) { cvs.width = width; cvs.height = height; } else { cvs.width = w; cvs.height = h; } x = (cvs.width - w) / 2; y = (cvs.height - h) / 2; opts.preserveHeaders || this._rotate2Orientaion( cvs, orientation ); this._renderImageToCanvas( cvs, img, x, y, w, h ); }, _rotate2Orientaion: function( canvas, orientation ) { var width = canvas.width, height = canvas.height, ctx = canvas.getContext('2d'); switch ( orientation ) { case 5: case 6: case 7: case 8: canvas.width = height; canvas.height = width; break; } switch ( orientation ) { case 2: // horizontal flip ctx.translate( width, 0 ); ctx.scale( -1, 1 ); break; case 3: // 180 rotate left ctx.translate( width, height ); ctx.rotate( Math.PI ); break; case 4: // vertical flip ctx.translate( 0, height ); ctx.scale( 1, -1 ); break; case 5: // vertical flip + 90 rotate right ctx.rotate( 0.5 * Math.PI ); ctx.scale( 1, -1 ); break; case 6: // 90 rotate right ctx.rotate( 0.5 * Math.PI ); ctx.translate( 0, -height ); break; case 7: // horizontal flip + 90 rotate right ctx.rotate( 0.5 * Math.PI ); ctx.translate( width, -height ); ctx.scale( -1, 1 ); break; case 8: // 90 rotate left ctx.rotate( -0.5 * Math.PI ); ctx.translate( -width, 0 ); break; } }, // https://github.com/stomita/ios-imagefile-megapixel/ // blob/master/src/megapix-image.js _renderImageToCanvas: (function() { // 濡傛灉涓嶆槸ios, 涓嶉渶瑕佽繖涔堝鏉傦紒 if ( !Base.os.ios ) { return function( canvas ) { var args = Base.slice( arguments, 1 ), ctx = canvas.getContext('2d'); ctx.drawImage.apply( ctx, args ); }; } /** * Detecting vertical squash in loaded image. * Fixes a bug which squash image vertically while drawing into * canvas for some images. */ function detectVerticalSquash( img, iw, ih ) { var canvas = document.createElement('canvas'), ctx = canvas.getContext('2d'), sy = 0, ey = ih, py = ih, data, alpha, ratio; canvas.width = 1; canvas.height = ih; ctx.drawImage( img, 0, 0 ); data = ctx.getImageData( 0, 0, 1, ih ).data; // search image edge pixel position in case // it is squashed vertically. while ( py > sy ) { alpha = data[ (py - 1) * 4 + 3 ]; if ( alpha === 0 ) { ey = py; } else { sy = py; } py = (ey + sy) >> 1; } ratio = (py / ih); return (ratio === 0) ? 1 : ratio; } // fix ie7 bug // http://stackoverflow.com/questions/11929099/ // html5-canvas-drawimage-ratio-bug-ios if ( Base.os.ios >= 7 ) { return function( canvas, img, x, y, w, h ) { var iw = img.naturalWidth, ih = img.naturalHeight, vertSquashRatio = detectVerticalSquash( img, iw, ih ); return canvas.getContext('2d').drawImage( img, 0, 0, iw * vertSquashRatio, ih * vertSquashRatio, x, y, w, h ); }; } /** * Detect subsampling in loaded image. * In iOS, larger images than 2M pixels may be * subsampled in rendering. */ function detectSubsampling( img ) { var iw = img.naturalWidth, ih = img.naturalHeight, canvas, ctx; // subsampling may happen overmegapixel image if ( iw * ih > 1024 * 1024 ) { canvas = document.createElement('canvas'); canvas.width = canvas.height = 1; ctx = canvas.getContext('2d'); ctx.drawImage( img, -iw + 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 ctx.getImageData( 0, 0, 1, 1 ).data[ 3 ] === 0; } else { return false; } } return function( canvas, img, x, y, width, height ) { var iw = img.naturalWidth, ih = img.naturalHeight, ctx = canvas.getContext('2d'), subsampled = detectSubsampling( img ), doSquash = this.type === 'image/jpeg', d = 1024, sy = 0, dy = 0, tmpCanvas, tmpCtx, vertSquashRatio, dw, dh, sx, dx; if ( subsampled ) { iw /= 2; ih /= 2; } ctx.save(); tmpCanvas = document.createElement('canvas'); tmpCanvas.width = tmpCanvas.height = d; tmpCtx = tmpCanvas.getContext('2d'); vertSquashRatio = doSquash ? detectVerticalSquash( img, iw, ih ) : 1; dw = Math.ceil( d * width / iw ); dh = Math.ceil( d * height / ih / vertSquashRatio ); while ( sy < ih ) { sx = 0; dx = 0; while ( sx < iw ) { tmpCtx.clearRect( 0, 0, d, d ); tmpCtx.drawImage( img, -sx, -sy ); ctx.drawImage( tmpCanvas, 0, 0, d, d, x + dx, y + dy, dw, dh ); sx += d; dx += dw; } sy += d; dy += dh; } ctx.restore(); tmpCanvas = tmpCtx = null; }; })() }); }); /** * @fileOverview Transport * @todo 鏀寔chunked浼犺緭锛屼紭鍔匡細 * 鍙互灏嗗ぇ鏂囦欢鍒嗘垚灏忓潡锛屾尐涓紶杈擄紝鍙互鎻愰珮澶ф枃浠舵垚鍔熺巼锛屽綋澶辫触鐨勬椂鍊欙紝涔熷彧闇€瑕侀噸浼犻偅灏忛儴鍒嗭紝 * 鑰屼笉闇€瑕侀噸澶村啀浼犱竴娆°€傚彟澶栨柇鐐圭画浼犱篃闇€瑕佺敤chunked鏂瑰紡銆 */ define('runtime/html5/transport',[ 'base', 'runtime/html5/runtime' ], function( Base, Html5Runtime ) { var noop = Base.noop, $ = Base.$; return Html5Runtime.register( 'Transport', { init: function() { this._status = 0; this._response = null; }, send: function() { var owner = this.owner, opts = this.options, xhr = this._initAjax(), blob = owner._blob, server = opts.server, formData, binary, fr; if ( opts.sendAsBinary ) { server += (/\?/.test( server ) ? '&' : '?') + $.param( owner._formData ); binary = blob.getSource(); } else { formData = new FormData(); $.each( owner._formData, function( k, v ) { formData.append( k, v ); }); formData.append( opts.fileVal, blob.getSource(), opts.filename || owner._formData.name || '' ); } if ( opts.withCredentials && 'withCredentials' in xhr ) { xhr.open( opts.method, server, true ); xhr.withCredentials = true; } else { xhr.open( opts.method, server ); } this._setRequestHeader( xhr, opts.headers ); if ( binary ) { // 寮哄埗璁剧疆鎴 content-type 涓烘枃浠舵祦銆 xhr.overrideMimeType && xhr.overrideMimeType('application/octet-stream'); // android鐩存帴鍙戦€乥lob浼氬鑷存湇鍔$鎺ユ敹鍒扮殑鏄┖鏂囦欢銆 // bug璇︽儏銆 // https://code.google.com/p/android/issues/detail?id=39882 // 鎵€浠ュ厛鐢╢ileReader璇诲彇鍑烘潵鍐嶉€氳繃arraybuffer鐨勬柟寮忓彂閫併€ if ( Base.os.android ) { fr = new FileReader(); fr.onload = function() { xhr.send( this.result ); fr = fr.onload = null; }; fr.readAsArrayBuffer( binary ); } else { xhr.send( binary ); } } else { xhr.send( formData ); } }, getResponse: function() { return this._response; }, getResponseAsJson: function() { return this._parseJson( this._response ); }, getStatus: function() { return this._status; }, abort: function() { var xhr = this._xhr; if ( xhr ) { xhr.upload.onprogress = noop; xhr.onreadystatechange = noop; xhr.abort(); this._xhr = xhr = null; } }, destroy: function() { this.abort(); }, _initAjax: function() { var me = this, xhr = new XMLHttpRequest(), opts = this.options; if ( opts.withCredentials && !('withCredentials' in xhr) && typeof XDomainRequest !== 'undefined' ) { xhr = new XDomainRequest(); } xhr.upload.onprogress = function( e ) { var percentage = 0; if ( e.lengthComputable ) { percentage = e.loaded / e.total; } return me.trigger( 'progress', percentage ); }; xhr.onreadystatechange = function() { if ( xhr.readyState !== 4 ) { return; } xhr.upload.onprogress = noop; xhr.onreadystatechange = noop; me._xhr = null; me._status = xhr.status; if ( xhr.status >= 200 && xhr.status < 300 ) { me._response = xhr.responseText; return me.trigger('load'); } else if ( xhr.status >= 500 && xhr.status < 600 ) { me._response = xhr.responseText; return me.trigger( 'error', 'server' ); } return me.trigger( 'error', me._status ? 'http' : 'abort' ); }; me._xhr = xhr; return xhr; }, _setRequestHeader: function( xhr, headers ) { $.each( headers, function( key, val ) { xhr.setRequestHeader( key, val ); }); }, _parseJson: function( str ) { var json; try { json = JSON.parse( str ); } catch ( ex ) { json = {}; } return json; } }); }); /** * @fileOverview Transport flash瀹炵幇 */ define('runtime/html5/md5',[ 'runtime/html5/runtime' ], function( FlashRuntime ) { /* * Fastest md5 implementation around (JKM md5) * Credits: Joseph Myers * * @see http://www.myersdaily.org/joseph/javascript/md5-text.html * @see http://jsperf.com/md5-shootout/7 */ /* this function is much faster, so if possible we use it. Some IEs are the only ones I know of that need the idiotic second function, generated by an if clause. */ var add32 = function (a, b) { return (a + b) & 0xFFFFFFFF; }, cmn = function (q, a, b, x, s, t) { a = add32(add32(a, q), add32(x, t)); return add32((a << s) | (a >>> (32 - s)), b); }, ff = function (a, b, c, d, x, s, t) { return cmn((b & c) | ((~b) & d), a, b, x, s, t); }, gg = function (a, b, c, d, x, s, t) { return cmn((b & d) | (c & (~d)), a, b, x, s, t); }, hh = function (a, b, c, d, x, s, t) { return cmn(b ^ c ^ d, a, b, x, s, t); }, ii = function (a, b, c, d, x, s, t) { return cmn(c ^ (b | (~d)), a, b, x, s, t); }, md5cycle = function (x, k) { var a = x[0], b = x[1], c = x[2], d = x[3]; a = ff(a, b, c, d, k[0], 7, -680876936); d = ff(d, a, b, c, k[1], 12, -389564586); c = ff(c, d, a, b, k[2], 17, 606105819); b = ff(b, c, d, a, k[3], 22, -1044525330); a = ff(a, b, c, d, k[4], 7, -176418897); d = ff(d, a, b, c, k[5], 12, 1200080426); c = ff(c, d, a, b, k[6], 17, -1473231341); b = ff(b, c, d, a, k[7], 22, -45705983); a = ff(a, b, c, d, k[8], 7, 1770035416); d = ff(d, a, b, c, k[9], 12, -1958414417); c = ff(c, d, a, b, k[10], 17, -42063); b = ff(b, c, d, a, k[11], 22, -1990404162); a = ff(a, b, c, d, k[12], 7, 1804603682); d = ff(d, a, b, c, k[13], 12, -40341101); c = ff(c, d, a, b, k[14], 17, -1502002290); b = ff(b, c, d, a, k[15], 22, 1236535329); a = gg(a, b, c, d, k[1], 5, -165796510); d = gg(d, a, b, c, k[6], 9, -1069501632); c = gg(c, d, a, b, k[11], 14, 643717713); b = gg(b, c, d, a, k[0], 20, -373897302); a = gg(a, b, c, d, k[5], 5, -701558691); d = gg(d, a, b, c, k[10], 9, 38016083); c = gg(c, d, a, b, k[15], 14, -660478335); b = gg(b, c, d, a, k[4], 20, -405537848); a = gg(a, b, c, d, k[9], 5, 568446438); d = gg(d, a, b, c, k[14], 9, -1019803690); c = gg(c, d, a, b, k[3], 14, -187363961); b = gg(b, c, d, a, k[8], 20, 1163531501); a = gg(a, b, c, d, k[13], 5, -1444681467); d = gg(d, a, b, c, k[2], 9, -51403784); c = gg(c, d, a, b, k[7], 14, 1735328473); b = gg(b, c, d, a, k[12], 20, -1926607734); a = hh(a, b, c, d, k[5], 4, -378558); d = hh(d, a, b, c, k[8], 11, -2022574463); c = hh(c, d, a, b, k[11], 16, 1839030562); b = hh(b, c, d, a, k[14], 23, -35309556); a = hh(a, b, c, d, k[1], 4, -1530992060); d = hh(d, a, b, c, k[4], 11, 1272893353); c = hh(c, d, a, b, k[7], 16, -155497632); b = hh(b, c, d, a, k[10], 23, -1094730640); a = hh(a, b, c, d, k[13], 4, 681279174); d = hh(d, a, b, c, k[0], 11, -358537222); c = hh(c, d, a, b, k[3], 16, -722521979); b = hh(b, c, d, a, k[6], 23, 76029189); a = hh(a, b, c, d, k[9], 4, -640364487); d = hh(d, a, b, c, k[12], 11, -421815835); c = hh(c, d, a, b, k[15], 16, 530742520); b = hh(b, c, d, a, k[2], 23, -995338651); a = ii(a, b, c, d, k[0], 6, -198630844); d = ii(d, a, b, c, k[7], 10, 1126891415); c = ii(c, d, a, b, k[14], 15, -1416354905); b = ii(b, c, d, a, k[5], 21, -57434055); a = ii(a, b, c, d, k[12], 6, 1700485571); d = ii(d, a, b, c, k[3], 10, -1894986606); c = ii(c, d, a, b, k[10], 15, -1051523); b = ii(b, c, d, a, k[1], 21, -2054922799); a = ii(a, b, c, d, k[8], 6, 1873313359); d = ii(d, a, b, c, k[15], 10, -30611744); c = ii(c, d, a, b, k[6], 15, -1560198380); b = ii(b, c, d, a, k[13], 21, 1309151649); a = ii(a, b, c, d, k[4], 6, -145523070); d = ii(d, a, b, c, k[11], 10, -1120210379); c = ii(c, d, a, b, k[2], 15, 718787259); b = ii(b, c, d, a, k[9], 21, -343485551); x[0] = add32(a, x[0]); x[1] = add32(b, x[1]); x[2] = add32(c, x[2]); x[3] = add32(d, x[3]); }, /* there needs to be support for Unicode here, * unless we pretend that we can redefine the MD-5 * algorithm for multi-byte characters (perhaps * by adding every four 16-bit characters and * shortening the sum to 32 bits). Otherwise * I suggest performing MD-5 as if every character * was two bytes--e.g., 0040 0025 = @%--but then * how will an ordinary MD-5 sum be matched? * There is no way to standardize text to something * like UTF-8 before transformation; speed cost is * utterly prohibitive. The JavaScript standard * itself needs to look at this: it should start * providing access to strings as preformed UTF-8 * 8-bit unsigned value arrays. */ md5blk = function (s) { var md5blks = [], i; /* Andy King said do it this way. */ for (i = 0; i < 64; i += 4) { md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); } return md5blks; }, md5blk_array = function (a) { var md5blks = [], i; /* Andy King said do it this way. */ for (i = 0; i < 64; i += 4) { md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24); } return md5blks; }, md51 = function (s) { var n = s.length, state = [1732584193, -271733879, -1732584194, 271733878], i, length, tail, tmp, lo, hi; for (i = 64; i <= n; i += 64) { md5cycle(state, md5blk(s.substring(i - 64, i))); } s = s.substring(i - 64); length = s.length; tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; for (i = 0; i < length; i += 1) { tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); } tail[i >> 2] |= 0x80 << ((i % 4) << 3); if (i > 55) { md5cycle(state, tail); for (i = 0; i < 16; i += 1) { tail[i] = 0; } } // Beware that the final length might not fit in 32 bits so we take care of that tmp = n * 8; tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); lo = parseInt(tmp[2], 16); hi = parseInt(tmp[1], 16) || 0; tail[14] = lo; tail[15] = hi; md5cycle(state, tail); return state; }, md51_array = function (a) { var n = a.length, state = [1732584193, -271733879, -1732584194, 271733878], i, length, tail, tmp, lo, hi; for (i = 64; i <= n; i += 64) { md5cycle(state, md5blk_array(a.subarray(i - 64, i))); } // Not sure if it is a bug, however IE10 will always produce a sub array of length 1 // containing the last element of the parent array if the sub array specified starts // beyond the length of the parent array - weird. // https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue a = (i - 64) < n ? a.subarray(i - 64) : new Uint8Array(0); length = a.length; tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; for (i = 0; i < length; i += 1) { tail[i >> 2] |= a[i] << ((i % 4) << 3); } tail[i >> 2] |= 0x80 << ((i % 4) << 3); if (i > 55) { md5cycle(state, tail); for (i = 0; i < 16; i += 1) { tail[i] = 0; } } // Beware that the final length might not fit in 32 bits so we take care of that tmp = n * 8; tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); lo = parseInt(tmp[2], 16); hi = parseInt(tmp[1], 16) || 0; tail[14] = lo; tail[15] = hi; md5cycle(state, tail); return state; }, hex_chr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'], rhex = function (n) { var s = '', j; for (j = 0; j < 4; j += 1) { s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; } return s; }, hex = function (x) { var i; for (i = 0; i < x.length; i += 1) { x[i] = rhex(x[i]); } return x.join(''); }, md5 = function (s) { return hex(md51(s)); }, //////////////////////////////////////////////////////////////////////////// /** * SparkMD5 OOP implementation. * * Use this class to perform an incremental md5, otherwise use the * static methods instead. */ SparkMD5 = function () { // call reset to init the instance this.reset(); }; // In some cases the fast add32 function cannot be used.. if (md5('hello') !== '5d41402abc4b2a76b9719d911017c592') { add32 = function (x, y) { var lsw = (x & 0xFFFF) + (y & 0xFFFF), msw = (x >> 16) + (y >> 16) + (lsw >> 16); return (msw << 16) | (lsw & 0xFFFF); }; } /** * Appends a string. * A conversion will be applied if an utf8 string is detected. * * @param {String} str The string to be appended * * @return {SparkMD5} The instance itself */ SparkMD5.prototype.append = function (str) { // converts the string to utf8 bytes if necessary if (/[\u0080-\uFFFF]/.test(str)) { str = unescape(encodeURIComponent(str)); } // then append as binary this.appendBinary(str); return this; }; /** * Appends a binary string. * * @param {String} contents The binary string to be appended * * @return {SparkMD5} The instance itself */ SparkMD5.prototype.appendBinary = function (contents) { this._buff += contents; this._length += contents.length; var length = this._buff.length, i; for (i = 64; i <= length; i += 64) { md5cycle(this._state, md5blk(this._buff.substring(i - 64, i))); } this._buff = this._buff.substr(i - 64); return this; }; /** * Finishes the incremental computation, reseting the internal state and * returning the result. * Use the raw parameter to obtain the raw result instead of the hex one. * * @param {Boolean} raw True to get the raw result, false to get the hex result * * @return {String|Array} The result */ SparkMD5.prototype.end = function (raw) { var buff = this._buff, length = buff.length, i, tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], ret; for (i = 0; i < length; i += 1) { tail[i >> 2] |= buff.charCodeAt(i) << ((i % 4) << 3); } this._finish(tail, length); ret = !!raw ? this._state : hex(this._state); this.reset(); return ret; }; /** * Finish the final calculation based on the tail. * * @param {Array} tail The tail (will be modified) * @param {Number} length The length of the remaining buffer */ SparkMD5.prototype._finish = function (tail, length) { var i = length, tmp, lo, hi; tail[i >> 2] |= 0x80 << ((i % 4) << 3); if (i > 55) { md5cycle(this._state, tail); for (i = 0; i < 16; i += 1) { tail[i] = 0; } } // Do the final computation based on the tail and length // Beware that the final length may not fit in 32 bits so we take care of that tmp = this._length * 8; tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); lo = parseInt(tmp[2], 16); hi = parseInt(tmp[1], 16) || 0; tail[14] = lo; tail[15] = hi; md5cycle(this._state, tail); }; /** * Resets the internal state of the computation. * * @return {SparkMD5} The instance itself */ SparkMD5.prototype.reset = function () { this._buff = ""; this._length = 0; this._state = [1732584193, -271733879, -1732584194, 271733878]; return this; }; /** * Releases memory used by the incremental buffer and other aditional * resources. If you plan to use the instance again, use reset instead. */ SparkMD5.prototype.destroy = function () { delete this._state; delete this._buff; delete this._length; }; /** * Performs the md5 hash on a string. * A conversion will be applied if utf8 string is detected. * * @param {String} str The string * @param {Boolean} raw True to get the raw result, false to get the hex result * * @return {String|Array} The result */ SparkMD5.hash = function (str, raw) { // converts the string to utf8 bytes if necessary if (/[\u0080-\uFFFF]/.test(str)) { str = unescape(encodeURIComponent(str)); } var hash = md51(str); return !!raw ? hash : hex(hash); }; /** * Performs the md5 hash on a binary string. * * @param {String} content The binary string * @param {Boolean} raw True to get the raw result, false to get the hex result * * @return {String|Array} The result */ SparkMD5.hashBinary = function (content, raw) { var hash = md51(content); return !!raw ? hash : hex(hash); }; /** * SparkMD5 OOP implementation for array buffers. * * Use this class to perform an incremental md5 ONLY for array buffers. */ SparkMD5.ArrayBuffer = function () { // call reset to init the instance this.reset(); }; //////////////////////////////////////////////////////////////////////////// /** * Appends an array buffer. * * @param {ArrayBuffer} arr The array to be appended * * @return {SparkMD5.ArrayBuffer} The instance itself */ SparkMD5.ArrayBuffer.prototype.append = function (arr) { // TODO: we could avoid the concatenation here but the algorithm would be more complex // if you find yourself needing extra performance, please make a PR. var buff = this._concatArrayBuffer(this._buff, arr), length = buff.length, i; this._length += arr.byteLength; for (i = 64; i <= length; i += 64) { md5cycle(this._state, md5blk_array(buff.subarray(i - 64, i))); } // Avoids IE10 weirdness (documented above) this._buff = (i - 64) < length ? buff.subarray(i - 64) : new Uint8Array(0); return this; }; /** * Finishes the incremental computation, reseting the internal state and * returning the result. * Use the raw parameter to obtain the raw result instead of the hex one. * * @param {Boolean} raw True to get the raw result, false to get the hex result * * @return {String|Array} The result */ SparkMD5.ArrayBuffer.prototype.end = function (raw) { var buff = this._buff, length = buff.length, tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], i, ret; for (i = 0; i < length; i += 1) { tail[i >> 2] |= buff[i] << ((i % 4) << 3); } this._finish(tail, length); ret = !!raw ? this._state : hex(this._state); this.reset(); return ret; }; SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish; /** * Resets the internal state of the computation. * * @return {SparkMD5.ArrayBuffer} The instance itself */ SparkMD5.ArrayBuffer.prototype.reset = function () { this._buff = new Uint8Array(0); this._length = 0; this._state = [1732584193, -271733879, -1732584194, 271733878]; return this; }; /** * Releases memory used by the incremental buffer and other aditional * resources. If you plan to use the instance again, use reset instead. */ SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy; /** * Concats two array buffers, returning a new one. * * @param {ArrayBuffer} first The first array buffer * @param {ArrayBuffer} second The second array buffer * * @return {ArrayBuffer} The new array buffer */ SparkMD5.ArrayBuffer.prototype._concatArrayBuffer = function (first, second) { var firstLength = first.length, result = new Uint8Array(firstLength + second.byteLength); result.set(first); result.set(new Uint8Array(second), firstLength); return result; }; /** * Performs the md5 hash on an array buffer. * * @param {ArrayBuffer} arr The array buffer * @param {Boolean} raw True to get the raw result, false to get the hex result * * @return {String|Array} The result */ SparkMD5.ArrayBuffer.hash = function (arr, raw) { var hash = md51_array(new Uint8Array(arr)); return !!raw ? hash : hex(hash); }; return FlashRuntime.register( 'Md5', { init: function() { // do nothing. }, loadFromBlob: function( file ) { var blob = file.getSource(), chunkSize = 2 * 1024 * 1024, chunks = Math.ceil( blob.size / chunkSize ), chunk = 0, owner = this.owner, spark = new SparkMD5.ArrayBuffer(), me = this, blobSlice = blob.mozSlice || blob.webkitSlice || blob.slice, loadNext, fr; fr = new FileReader(); loadNext = function() { var start, end; start = chunk * chunkSize; end = Math.min( start + chunkSize, blob.size ); fr.onload = function( e ) { spark.append( e.target.result ); owner.trigger( 'progress', { total: file.size, loaded: end }); }; fr.onloadend = function() { fr.onloadend = fr.onload = null; if ( ++chunk < chunks ) { setTimeout( loadNext, 1 ); } else { setTimeout(function(){ owner.trigger('load'); me.result = spark.end(); loadNext = file = blob = spark = null; owner.trigger('complete'); }, 50 ); } }; fr.readAsArrayBuffer( blobSlice.call( blob, start, end ) ); }; loadNext(); }, getResult: function() { return this.result; } }); }); /** * @fileOverview FlashRuntime */ define('runtime/flash/runtime',[ 'base', 'runtime/runtime', 'runtime/compbase' ], function( Base, Runtime, CompBase ) { var $ = Base.$, type = 'flash', components = {}; function getFlashVersion() { var version; try { version = navigator.plugins[ 'Shockwave Flash' ]; version = version.description; } catch ( ex ) { try { version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash') .GetVariable('$version'); } catch ( ex2 ) { version = '0.0'; } } version = version.match( /\d+/g ); return parseFloat( version[ 0 ] + '.' + version[ 1 ], 10 ); } function FlashRuntime() { var pool = {}, clients = {}, destroy = this.destroy, me = this, jsreciver = Base.guid('webuploader_'); Runtime.apply( me, arguments ); me.type = type; // 杩欎釜鏂规硶鐨勮皟鐢ㄨ€咃紝瀹為檯涓婃槸RuntimeClient me.exec = function( comp, fn/*, args...*/ ) { var client = this, uid = client.uid, args = Base.slice( arguments, 2 ), instance; clients[ uid ] = client; if ( components[ comp ] ) { if ( !pool[ uid ] ) { pool[ uid ] = new components[ comp ]( client, me ); } instance = pool[ uid ]; if ( instance[ fn ] ) { return instance[ fn ].apply( instance, args ); } } return me.flashExec.apply( client, arguments ); }; function handler( evt, obj ) { var type = evt.type || evt, parts, uid; parts = type.split('::'); uid = parts[ 0 ]; type = parts[ 1 ]; // console.log.apply( console, arguments ); if ( type === 'Ready' && uid === me.uid ) { me.trigger('ready'); } else if ( clients[ uid ] ) { clients[ uid ].trigger( type.toLowerCase(), evt, obj ); } // Base.log( evt, obj ); } // flash鐨勬帴鍙楀櫒銆 window[ jsreciver ] = function() { var args = arguments; // 涓轰簡鑳芥崟鑾峰緱鍒般€ setTimeout(function() { handler.apply( null, args ); }, 1 ); }; this.jsreciver = jsreciver; this.destroy = function() { // @todo 鍒犻櫎姹犲瓙涓殑鎵€鏈夊疄渚 return destroy && destroy.apply( this, arguments ); }; this.flashExec = function( comp, fn ) { var flash = me.getFlash(), args = Base.slice( arguments, 2 ); return flash.exec( this.uid, comp, fn, args ); }; // @todo } Base.inherits( Runtime, { constructor: FlashRuntime, init: function() { var container = this.getContainer(), opts = this.options, html; // if not the minimal height, shims are not initialized // in older browsers (e.g FF3.6, IE6,7,8, Safari 4.0,5.0, etc) container.css({ position: 'absolute', top: '-8px', left: '-8px', width: '9px', height: '9px', overflow: 'hidden' }); // insert flash object html = '' + '' + '' + '' + ''; container.html( html ); }, getFlash: function() { if ( this._flash ) { return this._flash; } this._flash = $( '#' + this.uid ).get( 0 ); return this._flash; } }); FlashRuntime.register = function( name, component ) { component = components[ name ] = Base.inherits( CompBase, $.extend({ // @todo fix this later flashExec: function() { var owner = this.owner, runtime = this.getRuntime(); return runtime.flashExec.apply( owner, arguments ); } }, component ) ); return component; }; if ( getFlashVersion() >= 11.4 ) { Runtime.addRuntime( type, FlashRuntime ); } return FlashRuntime; }); /** * @fileOverview FilePicker */ define('runtime/flash/filepicker',[ 'base', 'runtime/flash/runtime' ], function( Base, FlashRuntime ) { var $ = Base.$; return FlashRuntime.register( 'FilePicker', { init: function( opts ) { var copy = $.extend({}, opts ), len, i; // 淇Flash鍐嶆病鏈夎缃畉itle鐨勬儏鍐典笅鏃犳硶寮瑰嚭flash鏂囦欢閫夋嫨妗嗙殑bug. len = copy.accept && copy.accept.length; for ( i = 0; i < len; i++ ) { if ( !copy.accept[ i ].title ) { copy.accept[ i ].title = 'Files'; } } delete copy.button; delete copy.id; delete copy.container; this.flashExec( 'FilePicker', 'init', copy ); }, destroy: function() { this.flashExec( 'FilePicker', 'destroy' ); } }); }); /** * @fileOverview 鍥剧墖鍘嬬缉 */ define('runtime/flash/image',[ 'runtime/flash/runtime' ], function( FlashRuntime ) { return FlashRuntime.register( 'Image', { // init: function( options ) { // var owner = this.owner; // this.flashExec( 'Image', 'init', options ); // owner.on( 'load', function() { // debugger; // }); // }, loadFromBlob: function( blob ) { var owner = this.owner; owner.info() && this.flashExec( 'Image', 'info', owner.info() ); owner.meta() && this.flashExec( 'Image', 'meta', owner.meta() ); this.flashExec( 'Image', 'loadFromBlob', blob.uid ); } }); }); /** * @fileOverview Transport flash瀹炵幇 */ define('runtime/flash/transport',[ 'base', 'runtime/flash/runtime', 'runtime/client' ], function( Base, FlashRuntime, RuntimeClient ) { var $ = Base.$; return FlashRuntime.register( 'Transport', { init: function() { this._status = 0; this._response = null; this._responseJson = null; }, send: function() { var owner = this.owner, opts = this.options, xhr = this._initAjax(), blob = owner._blob, server = opts.server, binary; xhr.connectRuntime( blob.ruid ); if ( opts.sendAsBinary ) { server += (/\?/.test( server ) ? '&' : '?') + $.param( owner._formData ); binary = blob.uid; } else { $.each( owner._formData, function( k, v ) { xhr.exec( 'append', k, v ); }); xhr.exec( 'appendBlob', opts.fileVal, blob.uid, opts.filename || owner._formData.name || '' ); } this._setRequestHeader( xhr, opts.headers ); xhr.exec( 'send', { method: opts.method, url: server, forceURLStream: opts.forceURLStream, mimeType: 'application/octet-stream' }, binary ); }, getStatus: function() { return this._status; }, getResponse: function() { return this._response || ''; }, getResponseAsJson: function() { return this._responseJson; }, abort: function() { var xhr = this._xhr; if ( xhr ) { xhr.exec('abort'); xhr.destroy(); this._xhr = xhr = null; } }, destroy: function() { this.abort(); }, _initAjax: function() { var me = this, xhr = new RuntimeClient('XMLHttpRequest'); xhr.on( 'uploadprogress progress', function( e ) { var percent = e.loaded / e.total; percent = Math.min( 1, Math.max( 0, percent ) ); return me.trigger( 'progress', percent ); }); xhr.on( 'load', function() { var status = xhr.exec('getStatus'), readBody = false, err = '', p; xhr.off(); me._xhr = null; if ( status >= 200 && status < 300 ) { readBody = true; } else if ( status >= 500 && status < 600 ) { readBody = true; err = 'server'; } else { err = 'http'; } if ( readBody ) { me._response = xhr.exec('getResponse'); me._response = decodeURIComponent( me._response ); // flash 澶勭悊鍙兘瀛樺湪 bug, 娌¤緳鍙兘闈 js 浜 // try { // me._responseJson = xhr.exec('getResponseAsJson'); // } catch ( error ) { p = window.JSON && window.JSON.parse || function( s ) { try { return new Function('return ' + s).call(); } catch ( err ) { return {}; } }; me._responseJson = me._response ? p(me._response) : {}; // } } xhr.destroy(); xhr = null; return err ? me.trigger( 'error', err ) : me.trigger('load'); }); xhr.on( 'error', function() { xhr.off(); me._xhr = null; me.trigger( 'error', 'http' ); }); me._xhr = xhr; return xhr; }, _setRequestHeader: function( xhr, headers ) { $.each( headers, function( key, val ) { xhr.exec( 'setRequestHeader', key, val ); }); } }); }); /** * @fileOverview Blob Html瀹炵幇 */ define('runtime/flash/blob',[ 'runtime/flash/runtime', 'lib/blob' ], function( FlashRuntime, Blob ) { return FlashRuntime.register( 'Blob', { slice: function( start, end ) { var blob = this.flashExec( 'Blob', 'slice', start, end ); return new Blob( blob.uid, blob ); } }); }); /** * @fileOverview Md5 flash瀹炵幇 */ define('runtime/flash/md5',[ 'runtime/flash/runtime' ], function( FlashRuntime ) { return FlashRuntime.register( 'Md5', { init: function() { // do nothing. }, loadFromBlob: function( blob ) { return this.flashExec( 'Md5', 'loadFromBlob', blob.uid ); } }); }); /** * @fileOverview 瀹屽叏鐗堟湰銆 */ define('preset/all',[ 'base', // widgets 'widgets/filednd', 'widgets/filepaste', 'widgets/filepicker', 'widgets/image', 'widgets/queue', 'widgets/runtime', 'widgets/upload', 'widgets/validator', 'widgets/md5', // runtimes // html5 'runtime/html5/blob', 'runtime/html5/dnd', 'runtime/html5/filepaste', 'runtime/html5/filepicker', 'runtime/html5/imagemeta/exif', 'runtime/html5/androidpatch', 'runtime/html5/image', 'runtime/html5/transport', 'runtime/html5/md5', // flash 'runtime/flash/filepicker', 'runtime/flash/image', 'runtime/flash/transport', 'runtime/flash/blob', 'runtime/flash/md5' ], function( Base ) { return Base; }); /** * @fileOverview 鏃ュ織缁勪欢锛屼富瑕佺敤鏉ユ敹闆嗛敊璇俊鎭紝鍙互甯姪 webuploader 鏇村ソ鐨勫畾浣嶉棶棰樺拰鍙戝睍銆 * * 濡傛灉鎮ㄤ笉鎯宠鍚敤姝ゅ姛鑳斤紝璇峰湪鎵撳寘鐨勬椂鍊欏幓鎺 log 妯″潡銆 * * 鎴栬€呭彲浠ュ湪鍒濆鍖栫殑鏃跺€欓€氳繃 options.disableWidgets 灞炴€х鐢ㄣ€ * * 濡傦細 * WebUploader.create({ * ... * * disableWidgets: 'log', * * ... * }) */ define('widgets/log',[ 'base', 'uploader', 'widgets/widget' ], function( Base, Uploader ) { var $ = Base.$, logUrl = ' http://static.tieba.baidu.com/tb/pms/img/st.gif??', product = (location.hostname || location.host || 'protected').toLowerCase(), // 鍙拡瀵 baidu 鍐呴儴浜у搧鐢ㄦ埛鍋氱粺璁″姛鑳姐€ enable = product && /baidu/i.exec(product), base; if (!enable) { return; } base = { dv: 3, master: 'webuploader', online: /test/.exec(product) ? 0 : 1, module: '', product: product, type: 0 }; function send(data) { var obj = $.extend({}, base, data), url = logUrl.replace(/^(.*)\?/, '$1' + $.param( obj )), image = new Image(); image.src = url; } return Uploader.register({ name: 'log', init: function() { var owner = this.owner, count = 0, size = 0; owner .on('error', function(code) { send({ type: 2, c_error_code: code }); }) .on('uploadError', function(file, reason) { send({ type: 2, c_error_code: 'UPLOAD_ERROR', c_reason: '' + reason }); }) .on('uploadComplete', function(file) { count++; size += file.size; }). on('uploadFinished', function() { send({ c_count: count, c_size: size }); count = size = 0; }); send({ c_usage: 1 }); } }); }); /** * @fileOverview Uploader涓婁紶绫 */ define('webuploader',[ 'preset/all', 'widgets/log' ], function( preset ) { return preset; }); return require('webuploader'); });