Skip to content

Commit

Permalink
Merge branch 't/12806' into major
Browse files Browse the repository at this point in the history
  • Loading branch information
Reinmar committed Mar 5, 2015
2 parents 45ff334 + 45b9eac commit 148553f
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 46 deletions.
14 changes: 8 additions & 6 deletions core/editor.js
Expand Up @@ -1109,13 +1109,14 @@
* @returns {CKEDITOR.dom.documentFragment/String}
*/
getSelectedHtml: function( toString ) {
var editable = this.editable();
var editable = this.editable(),
ranges = this.getSelection().getRanges();

if ( !editable ) {
if ( !editable || ranges.length === 0 ) {
return null;
}

var docFragment = editable.getHtmlFromRange( this.getSelection().getRanges()[ 0 ] );
var docFragment = editable.getHtmlFromRange( ranges[ 0 ] );

return toString ? docFragment.getHtml() : docFragment;
},
Expand All @@ -1135,13 +1136,14 @@
* @returns {CKEDITOR.dom.documentFragment/String}
*/
extractSelectedHtml: function( toString ) {
var editable = this.editable();
var editable = this.editable(),
ranges = this.getSelection().getRanges();

if ( !editable ) {
if ( !editable || ranges.length === 0 ) {
return null;
}

var range = this.getSelection().getRanges()[ 0 ],
var range = ranges[ 0 ],
docFragment = editable.extractHtmlFromRange( range );

this.getSelection().selectRanges( [ range ] );
Expand Down
32 changes: 0 additions & 32 deletions core/selection.js
Expand Up @@ -1597,38 +1597,6 @@
return ( cache.selectedText = text );
},

/**
* Retrieves the HTML contained within the range. If selection
* contains multiple ranges method will return concatenation of HTMLs from ranges.
*
* var text = editor.getSelection().getSelectedText();
* alert( text );
*
* @since 4.4
* @returns {String} A string of HTML within the current selection.
*/
getSelectedHtml: function() {
var nativeSel = this.getNative();

if ( this.isFake ) {
return this.getSelectedElement().getHtml();
}

if ( nativeSel && nativeSel.createRange )
return nativeSel.createRange().htmlText;

if ( nativeSel.rangeCount > 0 ) {
var div = document.createElement( 'div' );

for ( var i = 0; i < nativeSel.rangeCount; i++ ) {
div.appendChild( nativeSel.getRangeAt( i ).cloneContents() );
}
return div.innerHTML;
}

return '';
},

/**
* Locks the selection made in the editor in order to make it possible to
* manipulate it without browser interference. A locked selection is
Expand Down
9 changes: 4 additions & 5 deletions plugins/clipboard/plugin.js
Expand Up @@ -499,7 +499,7 @@

// Delete content with the low priority so one can overwrite cut data.
editable.on( 'cut', function() {
editor.getSelection().getRanges()[ 0 ].deleteContents(); // @todo replace with the new delete content function
editor.extractSelectedHtml();
}, null, null, 999 );
}

Expand Down Expand Up @@ -1421,7 +1421,7 @@
// No we can safely delete content for the drag range...
dragRange = editor.createRange();
dragRange.moveToBookmark( dragBookmark );
dragRange.deleteContents(); // @todo replace with the new delete content function
editable.extractHtmlFromRange( dragRange );

// ...and paste content into the drop position.
dropRange = editor.createRange();
Expand All @@ -1445,7 +1445,7 @@
// Remove dragged content and make a snapshot.
dataTransfer.sourceEditor.fire( 'saveSnapshot' );

dragRange.deleteContents(); // @todo replace with the new delete content function
editable.extractHtmlFromRange( dragRange );

dataTransfer.sourceEditor.getSelection().reset();
dataTransfer.sourceEditor.fire( 'saveSnapshot' );
Expand Down Expand Up @@ -1944,8 +1944,7 @@
if ( editor ) {
this.sourceEditor = editor;

// @todo replace with the new function
this.setData( 'text/html', editor.getSelection().getSelectedHtml() );
this.setData( 'text/html', editor.getSelectedHtml( 1 ) );

// Without setData( 'text', ... ) on dragstart there is no drop event in Safari.
// Also 'text' data is empty as drop to the textarea does not work if we do not put there text.
Expand Down
35 changes: 35 additions & 0 deletions tests/core/editor/getextractselectedhtml.js
Expand Up @@ -9,7 +9,17 @@ bender.editor = {
}
};

var stubs = [];

bender.test( {
'tearDown': function() {
var stub;

while ( stub = stubs.pop() ) {
stub.restore();
}
},

'test getSelectedHtml': function() {
var editor = this.editor;
bender.tools.selection.setWithHtml( editor, '<p>fo{ob}ar</p>' );
Expand All @@ -27,6 +37,21 @@ bender.test( {
assert.areSame( 'ob', editor.getSelectedHtml( true ) );
},

'test getSelectedHtml with no ranges': function() {
// Only on Firefox it may happens that selection has no ranges.
if ( !CKEDITOR.env.gecko ) {
assert.ignore();
}

sinon.stub( CKEDITOR.dom.selection.prototype, 'getRanges' ).returns( [] );
stubs.push( CKEDITOR.dom.selection.prototype.getRanges );

var editor = this.editor,
selectedHtml = editor.getSelectedHtml();

assert.isNull( selectedHtml, 'There should be no error but null should be returns if selection contains no ranges' );
},

'test extractSelectedHtml': function() {
var editor = this.editor;
bender.tools.selection.setWithHtml( editor, '<p>fo{ob}ar</p>' );
Expand Down Expand Up @@ -54,5 +79,15 @@ bender.test( {
assert.areSame( 'ob', editor.extractSelectedHtml( true ) );
assert.isInnerHtmlMatching( '<p>fo^ar@</p>', bender.tools.selection.getWithHtml( editor ),
{ compareSelection: true, normalizeSelection: true }, 'contents of the editor' );
},

'test extractSelectedHtml with no ranges': function() {
sinon.stub( CKEDITOR.dom.selection.prototype, 'getRanges' ).returns( [] );
stubs.push( CKEDITOR.dom.selection.prototype.getRanges );

var editor = this.editor,
selectedHtml = editor.getSelectedHtml();

assert.isNull( selectedHtml, 'There should be no error but null should be returns if selection contains no ranges' );
}
} );
32 changes: 29 additions & 3 deletions tests/plugins/clipboard/drop.js
Expand Up @@ -344,6 +344,32 @@ var testsForMultipleEditor = {
} );
},

// Integration test (#12806).
'test drop part of the link': function( editor ) {
var bot = bender.editorBots[ editor.name ],
evt = bender.tools.mockDropEvent();

bot.setHtmlWithSelection( '<p id="p" style="margin-left: 20px"><a href="foo">Lorem [ipsum] dolor</a> sit amet.</p>' );
editor.resetUndo();

drag( editor, evt );

drop( editor, evt, {
element: editor.document.getById( 'p' ).getChild( 1 ),
offset: 4,
expectedTransferType: CKEDITOR.DATA_TRANSFER_INTERNAL,
expectedText: 'ipsum',
expectedHtml: '<a href="foo">ipsum</a>',
expectedDataType: 'html',
expectedDataValue: '<a href="foo">ipsum</a>'
}, null, function() {
assert.isInnerHtmlMatching(
'<p id="p" style="margin-left:20px"><a href="foo">Lorem dolor</a> sit<a data-cke-saved-href="foo" href="foo">' +
'ipsum' + ( ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) ? '</a>^' : '^</a>' ) + ' amet.@</p>',
getWithHtml( editor ), htmlMatchOpts, 'after drop' );
} );
},

'test drop text from external source': function( editor ) {
var bot = bender.editorBots[ editor.name ],
evt = bender.tools.mockDropEvent();
Expand Down Expand Up @@ -479,9 +505,9 @@ var testsForMultipleEditor = {
offset: 0,
expectedTransferType: CKEDITOR.DATA_TRANSFER_INTERNAL,
expectedText: 'drag1',
expectedHtml: 'drag1',
expectedHtml: '<b id="drag1">drag1</b>',
expectedDataType: 'html',
expectedDataValue: 'drag1'
expectedDataValue: '<b id="drag1">drag1</b>'
}, function( evt ) {
if ( !( CKEDITOR.env.ie && CKEDITOR.env.version == 8 ) && !CKEDITOR.env.safari ) {
assert.areSame( editor.document.getById( 'drag1' ), evt.data.dragRange.startContainer, 'dropRange.startContainer' );
Expand All @@ -492,7 +518,7 @@ var testsForMultipleEditor = {
evt.data.dropRange.setStart( editor.document.getById( 'drop2' ), 4 );
evt.data.dropRange.collapse( true );
}, function() {
assert.areSame( '<p>x<b id="drag1">xdrag1x</b>xx<b id="drop1">drop1</b>x<b id="drop2">drop2</b>drag1^x</p>', bender.tools.getHtmlWithSelection( editor ), 'after drop' );
assert.areSame( '<p>x<b id="drag1">xdrag1x</b>xx<b id="drop1">drop1</b>x<b id="drop2">drop2</b><b id="drag1">drag1^</b>x</p>', bender.tools.getHtmlWithSelection( editor ), 'after drop' );

editor.execCommand( 'undo' );

Expand Down

0 comments on commit 148553f

Please sign in to comment.