Skip to content

Commit

Permalink
Merge branch 't/12006' into major
Browse files Browse the repository at this point in the history
  • Loading branch information
oleq committed Jun 10, 2014
2 parents a9afb8d + 84d8423 commit 541f71b
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 34 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Expand Up @@ -3,6 +3,8 @@ CKEditor 4 Changelog

## CKEditor 4.5

* [#12006](http://dev.ckeditor.com/ticket/12006): [Nested widgets] Drag and drop of nested block widgets.

## CKEditor 4.4.2

Fixed Issues:
Expand Down
30 changes: 24 additions & 6 deletions plugins/widget/plugin.js
Expand Up @@ -2275,11 +2275,26 @@
if ( !el.is( CKEDITOR.dtd.$block ) )
return;

while ( el ) {
if ( isDomNestedEditable( el ) )
// Allow drop line inside, but never before or after nested editable (#12006).
if ( isDomNestedEditable( el ) )
return;

// If element is nested editable, make sure widget can be dropped there (#12006).
var nestedEditable = getNestedEditable( editable, el );
if ( nestedEditable ) {
var draggedWidget = widgetsRepo._.draggedWidget;

// Don't let the widget to be dropped into its own nested editable.
if ( widgetsRepo.getByElement( nestedEditable ) == draggedWidget )
return;

el = el.getParent();
var filter = CKEDITOR.filter.instances[ nestedEditable.data( 'cke-filter' ) ],
draggedRequiredContent = draggedWidget.requiredContent;

// There will be no relation if the filter of nested editable does not allow
// requiredContent of dragged widget.
if ( filter && draggedRequiredContent && !filter.check( draggedRequiredContent ) )
return;
}

return CKEDITOR.LINEUTILS_BEFORE | CKEDITOR.LINEUTILS_AFTER;
Expand Down Expand Up @@ -2952,10 +2967,13 @@
editor = this.editor,
editable = editor.editable(),
listeners = [],
sorted = [],
sorted = [];

// Mark dragged widget for repository#finder.
this.repository._.draggedWidget = this;

// Harvest all possible relations and display some closest.
relations = finder.greedySearch(),
// Harvest all possible relations and display some closest.
var relations = finder.greedySearch(),

buffer = CKEDITOR.tools.eventsBuffer( 50, function() {
locations = locator.locate( relations );
Expand Down
36 changes: 36 additions & 0 deletions tests/plugins/lineutils/_helpers/tools.js
@@ -0,0 +1,36 @@
var lineutilsTestsTools = ( function() {
'use strict';

return {
/**
* Asserts relations created by CKEDITOR.plugins.lineutils#finder method.
*
* @param {CKEDITOR.editor} editor Editor instance.
* @param {CKEDITOR.plugins.lineutils.finder} finder Finder instance after search (when finder#relations is present).
* @param {String} expected Expected HTML with relations marked by "|".
*/
assertRelations: function( editor, finder, expected ) {
var current, range,
ranges = [],
relations = finder.relations;

for ( var r in relations ) {
current = relations[ r ];

if ( current.type & CKEDITOR.LINEUTILS_BEFORE )
ranges.push( finder.getRange( { uid: r, type: CKEDITOR.LINEUTILS_BEFORE } ) );

if ( current.type & CKEDITOR.LINEUTILS_AFTER )
ranges.push( finder.getRange( { uid: r, type: CKEDITOR.LINEUTILS_AFTER } ) );

if ( current.type & CKEDITOR.LINEUTILS_INSIDE )
ranges.push( finder.getRange( { uid: r, type: CKEDITOR.LINEUTILS_INSIDE } ) );

while ( ( range = ranges.pop() ) )
range.insertNode( new CKEDITOR.dom.comment( 'R' ) );
}

assert.areSame( expected, editor.getData().replace( /<!--R-->/gi, '|' ), 'Relations discovered, collected and normalized correctly.' );
}
};
} )();
6 changes: 6 additions & 0 deletions tests/plugins/lineutils/finder.html
@@ -0,0 +1,6 @@
<head>
<script src="_helpers/tools.js"></script>
</head>
<body>

</body>
32 changes: 5 additions & 27 deletions tests/plugins/lineutils/finder.js
Expand Up @@ -6,7 +6,8 @@

var finder,
lookupEls1 = [],
lookupEls2 = [];
lookupEls2 = [],
assertRelations = lineutilsTestsTools.assertRelations;

bender.editor = {
config: {
Expand Down Expand Up @@ -68,29 +69,6 @@
}
}

function assertRelations( editor, expected, relations ) {
var current, range,
ranges = [];

for ( var r in relations ) {
current = relations[ r ];

if ( current.type & CKEDITOR.LINEUTILS_BEFORE )
ranges.push( finder.getRange( { uid: r, type: CKEDITOR.LINEUTILS_BEFORE } ) );

if ( current.type & CKEDITOR.LINEUTILS_AFTER )
ranges.push( finder.getRange( { uid: r, type: CKEDITOR.LINEUTILS_AFTER } ) );

if ( current.type & CKEDITOR.LINEUTILS_INSIDE )
ranges.push( finder.getRange( { uid: r, type: CKEDITOR.LINEUTILS_INSIDE } ) );

while ( ( range = ranges.pop() ) )
range.insertNode( editor.document.createText( '|' ) );
}

assert.areSame( expected, editor.getData(), 'Relations discovered, collected and normalized correctly.' );
}

function assertLookupElements( elements, msg, sort ) {
arrayAssert.itemsAreSame( elements, sort ? lookupEls1.sort() : lookupEls1, 'Lookup #1: ' + msg );
arrayAssert.itemsAreSame( elements, sort ? lookupEls2.sort() : lookupEls2, 'Lookup #2: ' + msg );
Expand Down Expand Up @@ -133,7 +111,7 @@
return doc.getById( 'x' );
},
assert: function( editor ) {
assertRelations( editor, '<p>a</p>|<div>|b|<p>|y|<span id="x">|x</span>|c</p>|d</div>|<p>e</p>', finder.relations );
assertRelations( editor, finder, '<p>a</p>|<div>|b|<p>|y|<span id="x">|x</span>|c</p>|d</div>|<p>e</p>' );
}
} ),

Expand All @@ -143,7 +121,7 @@
return doc.getById( 'x' );
},
assert: function( editor ) {
assertRelations( editor, '<p>a</p>|<div>|<p>|<span id="x">|x</span>|</p>|</div>|<p>b</p>', finder.relations );
assertRelations( editor, finder, '<p>a</p>|<div>|<p>|<span id="x">|x</span>|</p>|</div>|<p>b</p>' );
}
} ),

Expand All @@ -153,7 +131,7 @@
return doc.getById( 'x' );
},
assert: function( editor ) {
assertRelations( editor, '|<div contenteditable="true">|<p id="x">|x</p>|</div>|', finder.relations );
assertRelations( editor, finder, '|<div contenteditable="true">|<p id="x">|x</p>|</div>|' );
}
} ),

Expand Down
1 change: 1 addition & 0 deletions tests/plugins/widget/dnd.html
@@ -1,5 +1,6 @@
<head>
<script src="_helpers/tools.js"></script>
<script src="../lineutils/_helpers/tools.js"></script>
</head>
<body>

Expand Down
94 changes: 93 additions & 1 deletion tests/plugins/widget/dnd.js
Expand Up @@ -12,13 +12,37 @@
evt.editor.dataProcessor.writer.sortAttributes = 1;

evt.editor.widgets.add( 'testwidget', {} );

evt.editor.widgets.add( 'testwidget2', {
editables: {
n1: {
selector: '.n1',
allowedContent: 'p;blockquote(testwidget3)'
},
n2: {
selector: '.n2',
allowedContent: 'p;blockquote'
}
}
} );

evt.editor.widgets.add( 'testwidget3', {
requiredContent: 'blockquote(testwidget3)'
} );

evt.editor.widgets.add( 'testwidget4', {
editables: {
n1: '.n1'
}
} );
}
}
}
};

var fixHtml = widgetTestsTools.fixHtml,
getWidgetById = widgetTestsTools.getWidgetById;
getWidgetById = widgetTestsTools.getWidgetById,
assertRelations = lineutilsTestsTools.assertRelations;

function dropEvent( data, range ) {
var evt = new CKEDITOR.dom.event( {
Expand Down Expand Up @@ -369,6 +393,74 @@
revert();
}
} );
},

'test drag and drop - block widget into nested editable (ACF)': function() {
var editor = this.editor,
html = '<div data-widget="testwidget2">' +
'<div class="n1">' +
'<p>x</p>' +
'</div>' +
'<div class="n2">' +
'<p>y</p>' +
'</div>' +
'</div>' +
'<blockquote data-widget="testwidget3" class="testwidget3" id="w3">testwidget3</blockquote>';

this.editorBot.setData( html, function() {
var widget = getWidgetById( editor, 'w3' ),
repo = editor.widgets,
finder = repo.finder;

// Detach dragged widget from DOM to make assertion simpler.
widget.wrapper.remove();
repo._.draggedWidget = widget;
finder.greedySearch();

assertRelations( editor, finder, '|<div data-widget="testwidget2"><div class="n1">|<p>x</p>|</div><div class="n2"><p>y</p></div></div>|' );
} );
},

'test drag and drop - block widget into nested editable (ACF) - no filter': function() {
var editor = this.editor,
html = '<div data-widget="testwidget4">' +
'<div class="n1">' +
'<p>x</p>' +
'</div>' +
'</div>' +
'<blockquote data-widget="testwidget3" class="testwidget3" id="w3">testwidget3</blockquote>';

this.editorBot.setData( html, function() {
var widget = getWidgetById( editor, 'w3' ),
repo = editor.widgets,
finder = repo.finder;

// Detach dragged widget from DOM to make assertion simpler.
widget.wrapper.remove();
repo._.draggedWidget = widget;
finder.greedySearch();

assertRelations( editor, finder, '|<div data-widget="testwidget4"><div class="n1">|<p>x</p>|</div></div>|' );
} );
},

'test drag and drop - block widget into nested editable (ACF) - self-drop': function() {
var editor = this.editor,
html = '<div data-widget="testwidget4" id="w4">' +
'<div class="n1">' +
'<p>x</p>' +
'</div>' +
'</div>';

this.editorBot.setData( html, function() {
var repo = editor.widgets,
finder = repo.finder;

repo._.draggedWidget = getWidgetById( editor, 'w4' );
finder.greedySearch();

assertRelations( editor, finder, '|<div data-widget="testwidget4" id="w4"><div class="n1"><p>x</p></div></div>|' );
} );
}
} );
} )();

0 comments on commit 541f71b

Please sign in to comment.