diff --git a/CHANGES.md b/CHANGES.md
index c0234477ee7..992f9f2e026 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -32,6 +32,7 @@ Fixed Issues:
* [#12008](http://dev.ckeditor.com/ticket/12008): Fixed various cases of inserting a single non-editable element using the [`editor.insertHtml()`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-method-insertHtml) method. Fixes pasting a widget with a nested editable inside another widget's nested editable.
* [#12148](http://dev.ckeditor.com/ticket/12148): Fixed: [`dom.element.getChild()`](http://docs.ckeditor.com/#!/api/CKEDITOR.dom.element-method-getChild) should not modify passed array.
* [#12874](http://dev.ckeditor.com/ticket/12874): Fixed: Information about aggregated tasks should be somehow accessible in [aggregated#finished](http://docs.ckeditor.com/#!/api/CKEDITOR.plugins.notificationAggregator-event-finished).
+* [#12503](http://dev.ckeditor.com/ticket/12503): [Blink/Webkit] Fixed: Incorrect result of select all, backspace/delete.
Other Changes:
diff --git a/core/editable.js b/core/editable.js
index 08d44a11dab..2c564f47b80 100644
--- a/core/editable.js
+++ b/core/editable.js
@@ -2400,6 +2400,9 @@
if ( ( bogus = startBlock.getBogus() ) )
bogus.remove();
+ // Changing end container to element from text node (#12503).
+ range.enlarge( CKEDITOR.ENLARGE_INLINE );
+
// Delete range contents. Do NOT merge. Merging is weird.
range.deleteContents();
@@ -2419,6 +2422,13 @@
// Make sure the result selection is collapsed.
range = editor.getSelection().getRanges()[ 0 ];
range.collapse( 1 );
+
+ // Optimizing range containers from text nodes to elements (#12503).
+ range.optimize();
+ if ( range.startContainer.getHtml() === '' ) {
+ range.startContainer.appendBogus();
+ }
+
range.select();
return true;
diff --git a/tests/core/editable/keystrokes/delbackspacequirks/_helpers/tools.js b/tests/core/editable/keystrokes/delbackspacequirks/_helpers/tools.js
index c37cbbbc798..f2d8d55adff 100644
--- a/tests/core/editable/keystrokes/delbackspacequirks/_helpers/tools.js
+++ b/tests/core/editable/keystrokes/delbackspacequirks/_helpers/tools.js
@@ -11,9 +11,11 @@ var quirksTools = ( function() {
8: 'BACKSPACE'
};
- function assertKeystroke( key, keyModifiers, handled, html, expected ) {
+ function assertKeystroke( key, keyModifiers, handled, html, expected, normalizeSelection ) {
+ normalizeSelection = ( normalizeSelection === false ) ? false : true;
+
function decodeBoguses( html ) {
- return html.replace( /@/g, '
' );
+ return html.replace( /@/g, CKEDITOR.env.needsBrFiller ? '
' : '' );
}
return function() {
@@ -23,7 +25,7 @@ var quirksTools = ( function() {
html = decodeBoguses( html );
- bot.htmlWithSelection( html );
+ bender.tools.selection.setWithHtml( editor, html );
var listener = editor.on( 'key', function() {
++handledNatively;
@@ -35,8 +37,16 @@ var quirksTools = ( function() {
shiftKey: keyModifiers & CKEDITOR.SHIFT
} ) );
- assert.areSame( decodeBoguses( expected ),
- bender.tools.getHtmlWithSelection( editor.editable(), editor.document ).replace( /\u200b/g, '' ), '(' + keyNames[ key ] + ') Correct DOM state after the keystroke' );
+ var htmlWithSelection = bender.tools.selection.getWithHtml( editor );
+ var message = '(' + keyNames[ key ] + ') Correct DOM state after the keystroke';
+
+ assert.isInnerHtmlMatching(
+ expected,
+ htmlWithSelection,
+ { compareSelection: true, normalizeSelection: normalizeSelection },
+ message
+ );
+
assert.areSame( handled, handledNatively, '(' + keyNames[ key ] + ') Keystroke handled by the browser' );
listener.removeListener();
@@ -52,11 +62,11 @@ var quirksTools = ( function() {
}
function bf( html ) {
- return assertKeystroke.apply( this, [ BACKSPACE, 0, 1, html, html ] );
+ return assertKeystroke.apply( this, [ BACKSPACE, 0, 1, html, html, false ] );
}
function df( html ) {
- return assertKeystroke.apply( this, [ DEL, 0, 1, html, html ] );
+ return assertKeystroke.apply( this, [ DEL, 0, 1, html, html, false ] );
}
return {
@@ -92,4 +102,4 @@ var quirksTools = ( function() {
};
}
};
-} )();
\ No newline at end of file
+} )();
diff --git a/tests/core/editable/keystrokes/delbackspacequirks/collapsed.js b/tests/core/editable/keystrokes/delbackspacequirks/collapsed.js
index dbd5a7daedf..e3b11bfc5a0 100644
--- a/tests/core/editable/keystrokes/delbackspacequirks/collapsed.js
+++ b/tests/core/editable/keystrokes/delbackspacequirks/collapsed.js
@@ -36,7 +36,7 @@
this.editorBot.setData( '', function() {
editor.resetUndo();
- b( '
x
^y
', 'x^y
' ).call( tc ); + b( 'x
{}y
', 'x^y
' ).call( tc ); editor.execCommand( 'undo' ); assert.areSame( 'x
y
', editor.getData(), 'after 1st undo' ); @@ -59,125 +59,125 @@ } ); }, - 'test CTRL+backspace works as backspace when merging blocks': assertKeystroke( BACKSPACE, CKEDITOR.CTRL, 0, 'x
^y
', 'x^y
' ), - 'test SHIFT+backspace works as backspace when merging blocks': assertKeystroke( BACKSPACE, CKEDITOR.SHIFT, 0, 'x
^y
', 'x^y
' ), - 'test CTRL+delete works as delete when merging blocks': assertKeystroke( DEL, CKEDITOR.CTRL, 0, 'x^
y
', 'x^y
' ), - 'test SHIFT+delete works as delete when merging blocks': assertKeystroke( DEL, CKEDITOR.SHIFT, 0, 'x^
y
', 'x^y
' ), + 'test CTRL+backspace works as backspace when merging blocks': assertKeystroke( BACKSPACE, CKEDITOR.CTRL, 0, 'x
{}y
', 'x^y
' ), + 'test SHIFT+backspace works as backspace when merging blocks': assertKeystroke( BACKSPACE, CKEDITOR.SHIFT, 0, 'x
{}y
', 'x^y
' ), + 'test CTRL+delete works as delete when merging blocks': assertKeystroke( DEL, CKEDITOR.CTRL, 0, 'x{}
y
', 'x^y
' ), + 'test SHIFT+delete works as delete when merging blocks': assertKeystroke( DEL, CKEDITOR.SHIFT, 0, 'x{}
y
', 'x^y
' ), - 'test CTRL+backspace is not handled when not merging blocks': assertKeystroke( BACKSPACE, CKEDITOR.CTRL, 1, 'x^y
', 'x^y
' ), - 'test SHIFT+backspace is not handled when not merging blocks': assertKeystroke( BACKSPACE, CKEDITOR.SHIFT, 1, 'x^y
', 'x^y
' ), - 'test CTRL+delete is not handled when not merging blocks': assertKeystroke( DEL, CKEDITOR.CTRL, 1, 'x^y
', 'x^y
' ), - 'test SHIFT+delete is not handled when not merging blocks': assertKeystroke( DEL, CKEDITOR.SHIFT, 1, 'x^y
', 'x^y
' ), + 'test CTRL+backspace is not handled when not merging blocks': assertKeystroke( BACKSPACE, CKEDITOR.CTRL, 1, 'x{}y
', 'x^y
' ), + 'test SHIFT+backspace is not handled when not merging blocks': assertKeystroke( BACKSPACE, CKEDITOR.SHIFT, 1, 'x{}y
', 'x^y
' ), + 'test CTRL+delete is not handled when not merging blocks': assertKeystroke( DEL, CKEDITOR.CTRL, 1, 'x{}y
', 'x^y
' ), + 'test SHIFT+delete is not handled when not merging blocks': assertKeystroke( DEL, CKEDITOR.SHIFT, 1, 'x{}y
', 'x^y
' ), // --- BACKSPACE ------------------------------------------------------ - 'test backspace #1': b( 'x
^y
', 'x^y
' ), - 'test backspace #2': b( 'x
^y
', 'x^y
' ), - 'test backspace #3': b( 'x
', 'x^y
' ), - 'test backspace #4': b( 'x
', '^y
x^y
' ), - 'test backspace #5': b( '^y
', 'x
x^y
' ), - 'test backspace #7': b( 'x
^foo
', 'x^foo
' ), - 'test backspace #8': b( 'x
', '^y
x^y
foo
', + 'test backspace #1': b( '^y
x
[]y
', 'x^y
' ), + 'test backspace #2': b( 'x
[]y
', 'x^y
' ), + 'test backspace #3': b( 'x
', 'x^y
' ), + 'test backspace #4': b( 'x
', '[]y
x^y
' ), + 'test backspace #5': b( '[]y
', 'x
x^y
' ), + 'test backspace #7': b( 'x
[]foo
', 'x^foo
' ), + 'test backspace #8': b( 'x
', '[]y
x^y
foo
', '{}y
foo^y
x
^
', 'x^
' ), - 'test backspace #11': b( 'x
^y
x^y
x ^y |
x
[]@
', 'x^@!
' ), + 'test backspace #11': b( 'x
[]y
x^y
x []y |
x^y |
^y
^y
z
z
a
^y
', 'a
^y
' ), - 'test backspace #16': b( '^y
', '^y
' ), - 'test backspace #17': b( 'a
^y
', 'a
^y
' ), + 'test backspace #13': b( '[]y
[]y
z
z
a
[]y
', 'a
^y
' ), + 'test backspace #16': b( '[]y
', '^y
' ), + 'test backspace #17': b( 'a
[]y
', 'a
^y
' ), // Merge inline elements after keystroke. - 'test backspace, merge #1': b( 'x
^y
', 'x^y
' ), - 'test backspace, merge #2': b( 'x
^y
', 'x^y
' ), - 'test backspace, merge #3': b( '', '' ), - 'test backspace, merge #4': b( 'x
^y
z
x^y
z
x
^y
', 'x^y
' ), - 'test backspace, merge #6': b( 'x
^y
', 'x^y
' ), - 'test backspace, merge #7': b( 'x
^y
', 'x^y
' ), - 'test backspace, merge #8': b( 'x
^y
', + 'test backspace, merge #1': b( 'x
[]y
', 'x^y
' ), + 'test backspace, merge #2': b( 'x
[]y
', 'x^y
' ), + 'test backspace, merge #3': b( '', '' ), + 'test backspace, merge #4': b( 'x
[]y
z
x^y
z
x
[]y
', 'x^y
' ), + 'test backspace, merge #6': b( 'x
[]y
', 'x^y
' ), + 'test backspace, merge #7': b( 'x
[]y
', 'x^y
' ), + 'test backspace, merge #8': b( 'x
[]y
', 'x^y
' ), - 'test backspace, merge #9': b( 'x
^y
', + 'test backspace, merge #9': b( 'x
[]y
', 'x^y
' ), // Boguses. - 'test backspace, bogus #1': b( '@
^y
', '^y
' ), - 'test backspace, bogus #2': b( '@
^@
', '^@
' ), - 'test backspace, bogus #3': b( 'x
^@
', 'x^@
' ), - 'test backspace, bogus #4': b( '
@
^@
', '
^@
@
[]y
', '^y
' ), + 'test backspace, bogus #2': b( '@
[]@
', '^@!
' ), + 'test backspace, bogus #3': b( 'x
[]@
', 'x^@!
' ), + 'test backspace, bogus #4': b( '
@
[]@
', '
^@!
x
y^y
' ), - 'test backspace, no action #2': bf( 'x^y
' ), - 'test backspace, no action #3': bf( 'x
y^y
' ), - 'test backspace, no action #4': bf( 'x
' ), - 'test backspace, no action #5': bf( 'y^y
x
z' ), - 'test backspace, no action #6': bf( 'x^y
^y
' ), - 'test backspace, no action #7': bf( 'x
z^y
' ), + 'test backspace, no action #1': bf( 'x
y{}y
' ), + 'test backspace, no action #2': bf( 'x{}y
' ), + 'test backspace, no action #3': bf( 'x
y{}y
' ), + 'test backspace, no action #4': bf( 'x
' ), + 'test backspace, no action #5': bf( 'y{}y
x
z' ), + 'test backspace, no action #6': bf( 'x{}y
{}y
' ), + 'test backspace, no action #7': bf( 'x
z{}y
' ), // Handled by list or table plugin or editable, but not related to #9998. // This is just to control whether the fix for #9998 does not break some case which it should not handle at all. - 'test backspace, excluded #1': b( 'x
x
^y
' ), - 'test backspace, excluded #3': b( 'x
x
x
x
x | ^y |
x | ^y |
x | ^y |
x
x
^y
' ), + 'test backspace, excluded #3': b( 'x
x
x
x
x | []y |
x | ^y |
x | []y |
x | ^y |
x
^y |
x^
y |
x
[]y |
x^
y |
x^
y
', 'x^y
' ), - 'test delete #2': d( 'x^
y
', 'x^y
' ), - 'test delete #3': d( 'y
', 'x^y
' ), - 'test delete #4': d( 'x^
y
', '' ), - 'test delete #5': d( 'x^y
x^
x^y
' ), - 'test delete #6': d( 'y
', 'foo^
x
', 'foo^x
' ), - 'test delete #8': d( 'x^
y
' ), - 'test delete #9': d( 'x^y
x^
foo
x[]
y
', 'x^y
' ), + 'test delete #2': d( 'x[]
y
', 'x^y
' ), + 'test delete #3': d( 'y
', 'x^y
' ), + 'test delete #4': d( 'x[]
y
', '' ), + 'test delete #5': d( 'x^y
x[]
x^y
' ), + 'test delete #6': d( 'y
', 'foo[]
x
', 'foo^x
' ), + 'test delete #8': d( 'x[]
y
' ), + 'test delete #9': d( 'x^y
x[]
foo
' ), - 'test delete #10': d( 'x^foo
^
y
', '^y
' ), - 'test delete #13': d( 'y
y
z
z
y^
a
', 'y^
a
' ), - 'test delete #16': d( 'y^
y^
' ), - 'test delete #17': d( 'y^
a
', 'y^
a
' ), + 'test delete #10': d( '[]@
y
', '^y
' ), + 'test delete #13': d( 'y
y
z
z
y[]
a
', 'y^
a
' ), + 'test delete #16': d( 'y[]
y^
' ), + 'test delete #17': d( 'y[]
a
', 'y^
a
' ), // Merge inline elements after keystroke. - 'test delete, merge #1': d( 'x^
y
', 'x^y
' ), - 'test delete, merge #2': d( 'x^
y
', 'x^y
' ), - 'test delete, merge #3': d( '', '' ), - 'test delete, merge #4': d( 'x^
y
z
x^y
z
x[]
y
', 'x^y
' ), + 'test delete, merge #2': d( 'x[]
y
', 'x^y
' ), + 'test delete, merge #3': d( '', '' ), + 'test delete, merge #4': d( 'x[]
y
z
x^y
z
x^
@
', 'x^@
' ), - 'test delete, bogus #2': d( '@^
@
', '^@
' ), - 'test delete, bogus #3': d( '^@
x
', '^x
' ), - 'test delete, bogus #4': d( '^@
@
^
@
x[]
@
', 'x^@!
' ), + 'test delete, bogus #2': d( '@[]
@
', '^@!
' ), + 'test delete, bogus #3': d( '[]@
x
', '^x
' ), + 'test delete, bogus #4': d( '[]@
@
^
@!
x^x
y
' ), - 'test delete, no action #2': df( 'x^
y' ), - 'test delete, no action #3': df( 'x^x
y
' ), - 'test delete, no action #4': df( 'x^x
y
' ), - 'test delete, no action #5': df( 'x^
x
y
' ), - 'test delete, no action #6': df( 'x^
y' ), - 'test delete, no action #7': df( 'y^
yz
' ), + 'test delete, no action #1': df( 'x{}x
y
' ), + 'test delete, no action #2': df( 'x{}
y' ), + 'test delete, no action #3': df( 'x{}x
y
' ), + 'test delete, no action #4': df( 'x{}x
y
' ), + 'test delete, no action #5': df( 'x{}
x
y
' ), + 'test delete, no action #6': df( 'x{}
y' ), + 'test delete, no action #7': df( 'y{}
yz
' ), // Handled by list or table plugin or editable, but not related to #9998. // This is just to control whether the fix for #9998 does not break some case which it should not handle at all. - 'test delete, excluded #1': d( 'y
', 'y
', 'x^ | y |
x^ | y |
x^ | y |
y
', 'y
', 'x[] | y |
x^ | y |
x[] | y |
x^ | y |
x^ |
y
', 'x |
^y
' ) + 'test delete, excluded #6': d( 'x[] |
y
', 'x |
^y
' ) } ); -} )( quirksTools ); \ No newline at end of file +} )( quirksTools ); diff --git a/tests/core/editable/keystrokes/delbackspacequirks/expanded.js b/tests/core/editable/keystrokes/delbackspacequirks/expanded.js index e784ed212a4..b82a906c147 100644 --- a/tests/core/editable/keystrokes/delbackspacequirks/expanded.js +++ b/tests/core/editable/keystrokes/delbackspacequirks/expanded.js @@ -14,6 +14,9 @@ bender.test( { setUp: function() { + // Preventing removing empty tag. + delete CKEDITOR.dtd.$removeEmpty.small; + if ( !CKEDITOR.env.webkit ) assert.ignore(); }, @@ -79,6 +82,9 @@ 'test backspace and delete, bogus #3': bd( '[@
]@
', '^@
' ), 'test backspace and delete, bogus #4': bd( '@[
]@
', '^@
' ), + // #12503. + 'test backspace and delete, bogus #5': bd( 'bar
baz}
', 'x[x |
y]y
' ), 'test backspace and delete, no action #2': bdf( 'x[x | zz |
y]y
' ), @@ -87,4 +93,4 @@ 'test backspace and delete, no action #5': bdf( 'x[xy]y
' ), 'test backspace and delete, no action #6': bdf( 'x[x |
y]y |
Source
+Result:
+ + diff --git a/tests/core/editable/manual/notwantedelementsonselectallandbackspace.md b/tests/core/editable/manual/notwantedelementsonselectallandbackspace.md new file mode 100644 index 00000000000..b1377ceb602 --- /dev/null +++ b/tests/core/editable/manual/notwantedelementsonselectallandbackspace.md @@ -0,0 +1,12 @@ +@bender-tags: 4.5.0, tc +@bender-ui: collapsed +@bender-ckeditor-plugins: format, stylescombo, toolbar, wysiwygarea, undo + +---- + +1. Focus editor. +2. Select whole text using shortcut. +3. Press `Backspace` or `Delete`. + +**Expected result:** There should be no `` element in result and bogus `` in an editable.