210 lines
6.5 KiB
JavaScript
210 lines
6.5 KiB
JavaScript
/**
|
|
* @fileOverview FilePaste
|
|
*/
|
|
define([
|
|
'../../base',
|
|
'./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 ) {
|
|
}
|
|
|
|
me.dndOver = false;
|
|
me.elem.removeClass( prefix + 'over' );
|
|
|
|
if ( !dataTransfer || data ) {
|
|
return;
|
|
}
|
|
|
|
me._getTansferFiles( dataTransfer, function( results ) {
|
|
me.trigger( 'drop', $.map( results, function( file ) {
|
|
return new File( ruid, file );
|
|
}) );
|
|
});
|
|
|
|
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 );
|
|
}
|
|
}
|
|
});
|
|
});
|