diff --git a/plugins/clipboard/plugin.js b/plugins/clipboard/plugin.js index f779c535d51..0133104a704 100644 --- a/plugins/clipboard/plugin.js +++ b/plugins/clipboard/plugin.js @@ -1307,6 +1307,12 @@ } } ); + // We need to call preventDefault on dragover because otherwise if + // we drop image it will overwrite document. + editable.attachListener( dropTarget, 'dragover', function( evt ) { + evt.data.preventDefault(); + } ); + editable.attachListener( dropTarget, 'drop', function( evt ) { // Cancel native drop. evt.data.preventDefault(); @@ -1807,6 +1813,7 @@ chromeWindowsRegExp: /([\s\S]*)/, data: {}, + files: [], normalizeType: function( type ) { type = type.toLowerCase(); @@ -2017,7 +2024,8 @@ return; } - var that = this; + var that = this, + i; function getAndSetData( type ) { var data = that.getData( type ); @@ -2026,14 +2034,48 @@ } } + // Copy data. if ( CKEDITOR.env.ie ) { getAndSetData( 'Text' ); getAndSetData( 'URL' ); } else if ( this.$.types ) { - for ( var i = 0; i < this.$.types.length; i++ ) { + for ( i = 0; i < this.$.types.length; i++ ) { getAndSetData( this.$.types[ i ] ); } } + + // Copy files references. + if ( this.$ && this.$.files ) { + this._.files = []; + + for ( i = 0; i < this.$.files.length; i++ ) { + this._.files.push( this.$.files[ i ] ); + } + } + }, + + getFilesCount: function() { + if ( this._.files.length ) { + return this._.files.length; + } + + if ( this.$ && this.$.files && this.$.files.length ) { + return this.$.files.length; + } + + return 0; + }, + + getFile: function( i ) { + if ( this._.files.length ) { + return this._.files[ i ]; + } + + if ( this.$ && this.$.files && this.$.files.length ) { + return this.$.files[ i ]; + } + + return null; }, /** @@ -2045,6 +2087,11 @@ var typesToCheck = {}, type; + // If dataTransfer contains files it is not empty. + if ( this.getFilesCount() ) { + return false; + } + // Add custom types. for ( type in this._.data ) { typesToCheck[ type ] = 1; diff --git a/tests/_benderjs/ckeditor/static/tools.js b/tests/_benderjs/ckeditor/static/tools.js index bdcc697c0e0..e279e8e9016 100644 --- a/tests/_benderjs/ckeditor/static/tools.js +++ b/tests/_benderjs/ckeditor/static/tools.js @@ -777,6 +777,7 @@ mockNativeDataTransfer: function() { return { types: [], + files: CKEDITOR.env.ie && CKEDITOR.env.version < 10 ? undefined : [], _data: [], // Emulate browsers native behavior for getDeta/setData. setData: function( type, data ) { diff --git a/tests/plugins/clipboard/datatransfer.js b/tests/plugins/clipboard/datatransfer.js index cbc23e9f618..2579e61e942 100644 --- a/tests/plugins/clipboard/datatransfer.js +++ b/tests/plugins/clipboard/datatransfer.js @@ -348,7 +348,58 @@ bender.test( { assert.areSame( 'foo', dataTransfer.getData( 'cke/custom' ) ); assert.areSame( '', dataTransfer.getData( 'cke/undefined' ) ); + }, + + 'test files empty': function() { + var nativeData = bender.tools.mockNativeDataTransfer(), + dataTransfer = new CKEDITOR.plugins.clipboard.dataTransfer( nativeData ); + dataTransfer.cacheData(); + + assert.areSame( 0, dataTransfer.getFilesCount() ); + assert.isFalse( !!dataTransfer.getFile( 0 ) ); + }, + + 'test files': function() { + if ( CKEDITOR.env.ie && CKEDITOR.env.version < 10 ) { + assert.ignore(); + } + + var nativeData = bender.tools.mockNativeDataTransfer(), + dataTransfer = new CKEDITOR.plugins.clipboard.dataTransfer( nativeData ); + + nativeData.files.push( 'foo' ); + nativeData.files.push( 'bar' ); + + assert.areSame( 2, dataTransfer.getFilesCount() ); + assert.areSame( 'foo', dataTransfer.getFile( 0 ) ); + assert.areSame( 'bar', dataTransfer.getFile( 1 ) ); + }, + + 'test files with cache': function() { + if ( CKEDITOR.env.ie && CKEDITOR.env.version < 10 ) { + assert.ignore(); + } + + var nativeData = bender.tools.mockNativeDataTransfer(), + dataTransfer = new CKEDITOR.plugins.clipboard.dataTransfer( nativeData ); + + nativeData.files.push( 'foo' ); + nativeData.files.push( 'bar' ); + + dataTransfer.cacheData(); + + assert.areSame( 2, dataTransfer.getFilesCount() ); + assert.areSame( 'foo', dataTransfer.getFile( 0 ) ); + assert.areSame( 'bar', dataTransfer.getFile( 1 ) ); + assert.isFalse( !!dataTransfer.getFile( 2 ) ); + + nativeData.files = []; + + assert.areSame( 2, dataTransfer.getFilesCount() ); + assert.areSame( 'foo', dataTransfer.getFile( 0 ) ); + assert.areSame( 'bar', dataTransfer.getFile( 1 ) ); + assert.isFalse( !!dataTransfer.getFile( 2 ) ); }, 'test isEmpty 1': function() { @@ -437,6 +488,34 @@ bender.test( { assert.isFalse( dataTransfer.isEmpty() ); }, + 'test isEmpty 11': function() { + if ( CKEDITOR.env.ie && CKEDITOR.env.version < 10 ) { + assert.ignore(); + } + + var nativeData = bender.tools.mockNativeDataTransfer(), + dataTransfer = new CKEDITOR.plugins.clipboard.dataTransfer( nativeData ); + + nativeData.files.push( 'foo' ); + + assert.isFalse( dataTransfer.isEmpty() ); + }, + + 'test isEmpty 12': function() { + if ( CKEDITOR.env.ie && CKEDITOR.env.version < 10 ) { + assert.ignore(); + } + + var nativeData = bender.tools.mockNativeDataTransfer(), + dataTransfer = new CKEDITOR.plugins.clipboard.dataTransfer( nativeData ); + + nativeData.files.push( 'foo' ); + dataTransfer.cacheData(); + nativeData.files = []; + + assert.isFalse( dataTransfer.isEmpty() ); + }, + 'test initDragDataTransfer binding': function() { var nativeData1 = bender.tools.mockNativeDataTransfer(), nativeData2 = bender.tools.mockNativeDataTransfer(),