239 lines
6.9 KiB
JavaScript
239 lines
6.9 KiB
JavaScript
/**
|
||
* @fileOverview 组件基类。
|
||
*/
|
||
define([
|
||
'../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,
|
||
|
||
// 类Backbone的事件监听声明,监听uploader实例上的事件
|
||
// widget直接无法监听事件,事件只能通过uploader来传递
|
||
invoke: function( apiName, args ) {
|
||
|
||
/*
|
||
{
|
||
'make-thumb': 'makeThumb'
|
||
}
|
||
*/
|
||
var map = this.responseMap;
|
||
|
||
// 如果无API响应声明则忽略
|
||
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用来初始化widgets
|
||
_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 );
|
||
}
|
||
}
|
||
}
|
||
|
||
// 如果有callback,则用异步方式。
|
||
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;
|
||
}); |