diff --git a/CHANGES.md b/CHANGES.md index ef59cc53de5..7ab0bd3ede4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -21,6 +21,7 @@ Fixed Issues: * [#12398](http://dev.ckeditor.com/ticket/12398): Fixed: Maximize does not work on instance without a [title](http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-title). * [#12097](http://dev.ckeditor.com/ticket/12097): Fixed: JAWS not reading number of list options correctly in colors list box. * [#12411](http://dev.ckeditor.com/ticket/12411): Fixed: [Page Break](http://ckeditor.com/addon/pagebreak) used directly in the editable breaks the editor. +* [#12162](http://dev.ckeditor.com/ticket/12162): Fixed: Auto paragraphing and enter key in nested editables. ## CKEditor 4.4.4 diff --git a/core/editable.js b/core/editable.js index 8c713e97e8c..b39271057f9 100644 --- a/core/editable.js +++ b/core/editable.js @@ -1099,9 +1099,10 @@ // Whether in given context (pathBlock, pathBlockLimit and editor settings) // editor should automatically wrap inline contents with blocks. function shouldAutoParagraph( editor, pathBlock, pathBlockLimit ) { + // Check whether pathBlock equals pathBlockLimit to support nested editable (#12162). return editor.config.autoParagraph !== false && editor.activeEnterMode != CKEDITOR.ENTER_BR && - editor.editable().equals( pathBlockLimit ) && !pathBlock; + ( editor.editable().equals( pathBlockLimit ) && !pathBlock ) || ( pathBlock && pathBlock.getAttribute( 'contenteditable' ) == 'true' ); } // Matching an empty paragraph at the end of document. diff --git a/plugins/enterkey/plugin.js b/plugins/enterkey/plugin.js index ddbdd1a888b..d0bca5a9c2c 100644 --- a/plugins/enterkey/plugin.js +++ b/plugins/enterkey/plugin.js @@ -4,6 +4,22 @@ */ ( function() { + + function replaceRangeWithClosestEditableRoot( range ) { + var closestEditable = range.startContainer.getAscendant( function( node ) { + return node.type == CKEDITOR.NODE_ELEMENT && node.getAttribute( 'contenteditable' ) == 'true'; + }, true ); + + if ( range.root.equals( closestEditable ) ) { + return range; + } else { + var newRange = new CKEDITOR.dom.range( closestEditable ); + + newRange.moveToRange( range ); + return newRange; + } + } + CKEDITOR.plugins.add( 'enterkey', { init: function( editor ) { editor.addCommand( 'enter', { @@ -42,6 +58,10 @@ if ( !range ) return; + // When range is in nested editable, we have to replace range with this one, + // which have root property set to closest editable, to make auto paragraphing work. (#12162) + range = replaceRangeWithClosestEditableRoot( range ); + var doc = range.document; var atBlockStart = range.checkStartOfBlock(), diff --git a/tests/core/config/ignoreEmptyParagraph.js b/tests/core/config/ignoreEmptyParagraph.js index 9b50e85fa90..305576c5fef 100644 --- a/tests/core/config/ignoreEmptyParagraph.js +++ b/tests/core/config/ignoreEmptyParagraph.js @@ -1,4 +1,4 @@ -/* bender-tags: editor,unit */ +/* bender-tags: editor,unit,autoparagraphing */ /* bender-ckeditor-plugins: entities */ bender.test( diff --git a/tests/core/editable/domfix.js b/tests/core/editable/domfix.js index 24a60cc8204..e0d35b78319 100644 --- a/tests/core/editable/domfix.js +++ b/tests/core/editable/domfix.js @@ -1,4 +1,4 @@ -/* bender-tags: editor,unit */ +/* bender-tags: editor,unit,autoparagraphing */ var doc = CKEDITOR.document, tools = bender.tools; diff --git a/tests/core/editable/domfix2.js b/tests/core/editable/domfix2.js index a076a71ee23..692ea9c0609 100644 --- a/tests/core/editable/domfix2.js +++ b/tests/core/editable/domfix2.js @@ -1,4 +1,4 @@ -/* bender-tags: editor,unit */ +/* bender-tags: editor,unit,autoparagraphing */ var doc = CKEDITOR.document; // This group of tests plays upon the framed content. diff --git a/tests/core/editable/domfixnestededitable.js b/tests/core/editable/domfixnestededitable.js new file mode 100644 index 00000000000..be9e238bd70 --- /dev/null +++ b/tests/core/editable/domfixnestededitable.js @@ -0,0 +1,60 @@ +/* bender-tags: editor,unit,autoparagraphing */ + +( function () { + 'use strict'; + + var doc = CKEDITOR.document; + + bender.test( { + // Initialize the editor instance. + 'async:init': function() { + var that = this; + + bender.tools.setUpEditors( { + editor1: { + name: 'editor1' + } + }, function( editors, bots ) { + that.editors = editors; + that.callback(); + } ); + }, + + // (#12162) + 'test autoparagraphing in nested editable': function() { + var editor = this.editors.editor1, + editable = editor.editable(), + expected = + '

foo@

' + + '
' + + '
' + + '

^hello@

' + + '
' + + '
', + htmlMatchingOpts = { + compareSelection: true, + normalizeSelection: true + }; + + bender.tools.selection.setWithHtml( editor, + '

f[o]o

' + + '
' + + '
' + + 'hello' + + '
' + + '
' ); + + var nestedEditable = editable.findOne( 'div[contenteditable="true"]' ), + sel = editor.getSelection(), + range = editor.createRange(); + + nestedEditable.focus(); + range.setStart( nestedEditable, 0 ); + range.setEnd( nestedEditable, 0 ); + sel.selectRanges( [ range ] ); + + assert.isInnerHtmlMatching( expected, bender.tools.selection.getWithHtml( editor ), + htmlMatchingOpts, 'Paragraph should be added.' ); + } + } ); +} )(); \ No newline at end of file diff --git a/tests/core/selection/editor.js b/tests/core/selection/editor.js index 773aec6c4f8..501c612fbe2 100644 --- a/tests/core/selection/editor.js +++ b/tests/core/selection/editor.js @@ -1,4 +1,4 @@ -/* bender-tags: editor,unit */ +/* bender-tags: editor,unit,autoparagraphing */ 'use strict'; diff --git a/tests/plugins/enter/enterkey.js b/tests/plugins/enter/enterkey.js index 58cfd68cb90..c1b0adc036f 100644 --- a/tests/plugins/enter/enterkey.js +++ b/tests/plugins/enter/enterkey.js @@ -187,6 +187,31 @@ assert.areSame( '

foo

bar

', bot.getData(), 'main mode was used' ); }, + // (#12162) + 'test enter key directly in nested editable': function() { + var editor = this.editors.editorNoAutoParagraph, + expected = '

foo

' + + '
' + + '
' + + '

hell@

' + + '

@

' + + '
' + + '
'; + + bender.tools.selection.setWithHtml( editor, + '

foo

' + + '
' + + '
' + + 'hell[o]' + + '
' + + '
' ); + + editor.execCommand( 'enter' ); + + assert.isInnerHtmlMatching( expected, editor.editable().getHtml().replace( / data-cke-expando="\d+"/g, '' ), + 'New paragraphs should be created.' ); + }, + /* // Commented out until we decide whether we want to block enter key completely and how. 'test enter key is completely blocked if neither p nor br are allowed': function() { @@ -218,7 +243,7 @@ 'test shift+enter key - end of block, inside inline element followed by bogus br': se( 'editor', '

foo{}

', '

foo
^

' ), 'test shift+enter key - end of list item, inside inline element followed by bogus br': - se( 'editor', '', '' ), + se( 'editor', '', '' ) } ); } )(); \ No newline at end of file