Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#704] Fix broken widget after using Ctrl+Z in Edge #734

Merged
merged 9 commits into from
Sep 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions plugins/wysiwygarea/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,12 @@
doc.getDocumentElement().addClass( doc.$.compatMode );
}

// Prevent IE/Edge from leaving a new paragraph/div after deleting all contents in body. (http://dev.ckeditor.com/ticket/6966, http://dev.ckeditor.com/ticket/13142)
// Prevent IE/Edge from leaving a new paragraph/div after deleting all contents in body (http://dev.ckeditor.com/ticket/6966, http://dev.ckeditor.com/ticket/13142).
if ( CKEDITOR.env.ie && !CKEDITOR.env.edge && editor.enterMode != CKEDITOR.ENTER_P ) {
removeSuperfluousElement( 'p' );
} else if ( CKEDITOR.env.edge && editor.enterMode != CKEDITOR.ENTER_DIV ) {
}
// Starting from Edge 15 additional `div` is not added to the editor.
else if ( CKEDITOR.env.edge && CKEDITOR.env.version < 15 && editor.enterMode != CKEDITOR.ENTER_DIV ) {
removeSuperfluousElement( 'div' );
}

Expand Down Expand Up @@ -297,7 +299,7 @@
var elements = doc.getElementsByTag( tagName );
if ( lockRetain ) {
if ( elements.count() == 1 && !elements.getItem( 0 ).getCustomData( 'retain' ) &&
!elements.getItem( 0 ).hasAttribute( 'data-cke-temp' ) ) {
CKEDITOR.tools.isEmpty( elements.getItem( 0 ).getAttributes() ) ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason of this change? Previously elements without data-cke-temp attribute (so not temporary elements) were removed inside this if, now it removes only attributeless elements. Is this change necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Entire function removeSuperfluousElement was design to remove additional div which appear in Edge, when all text is removed from editor. This div never had any attribute. Unfortunately author hadn't predict that not only those extra divs might appear, but also widgets might be construct based on div. And in case of undo command entire widget might be redraw so we lost retain customData attached to div.
This change detects more carefully only those extra divs from Edge, so it becomes more specific. Now divs connected to widgets won't be removed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense 👍

elements.getItem( 0 ).remove( 1 );
}
lockRetain = false;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<textarea id="editor1" name="editor1">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test fails on IE8 due to addEventListener, if it should be run only for Edge add a proper bender.ignore or fix attaching listener if it should be run also for IE8.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added both things. I know it wasn't necessary, but this not harm anything. ;)

<figure class="image illustration" style="float:left">
<img alt="" height="266" src="http://c.cksource.com/a/1/img/demo/brownie.jpg" width="400" />
<figcaption>Bon App&eacute;tit!</figcaption>
</figure>
<p>Preheat the oven to <strong>350°F</strong> and grease the baking pan.
Combine the flour, sugar and cocoa powder in a medium bowl. In another small bowl, whisk together the butter and eggs. Stir the two mixtures until just combined.
Bake the brownies for 25 to 35 minutes. Remove from the oven and let it cool for 5 minutes.
</p>
</textarea>
<pre id="output" style="background-color: lightgreen;"></pre>
<script>
if ( !CKEDITOR.env.edge ) {
bender.ignore();
}

var editor = CKEDITOR.replace( 'editor1', {
height: '600px'
} );
var output = document.getElementById( 'output' );
editor.on( 'instanceReady', function() {
editor.editable().$.onkeyup = function() {
output.innerText = editor.editable().getFirst().getName();
};
} );
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@bender-ui: collapsed
@bender-tags: bug, 4.8.0, 704
@bender-ckeditor-plugins: image2, wysiwygarea, undo, sourcearea

----
1. Put caret in the text on the right and type some text.
1. Use `Ctrl + Z` or `Cmd + Z` shortcut to make undo few times.

**Expected:** Text returns to previous form. Below the editor, you should see `div` on green background.

**Unexpected:** Text moves below the image. Below editor, it will be written `figure` instead of `div` on the green background.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/* bender-ckeditor-plugins: widget,wysiwygarea,undo,toolbar */


( function() {
'use strict';

bender.editor = {
config: {
allowedContent: true
}
};

bender.test( {
// #704
'test keeping widget wrapper in editor when superfluous elements are checked': function() {
CKEDITOR.plugins.add( 'test', {
requires: 'widget',
init: function( editor ) {
editor.widgets.add( 'test', {
upcast: function( element ) {
if ( element.hasClass( 'test' ) ) {
return true;
}
},

init: function() {
this.element.setStyle( 'background-color', '#FFBB00' );
this.element.setStyle( 'padding', '30px' );
}
} );
}
} );
bender.editorBot.create( {
name: 'test_widget',
startupData: '<h2 class="test">Test</h2><p>Preheat the oven to</p>',
config: {
extraPlugins: 'test',
allowedContent: true
}
}, function( bot ) {
var editor = bot.editor;

editor.editable().fire( 'keydown', new CKEDITOR.dom.event( {
keyCode: 90,
ctrlKey: true,
shiftKey: false
} ) );

var snap = editor.getSnapshot();
editor.loadSnapshot( snap );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This two lines just reload the snapshot, it it needed here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.
keydown and keyup don't trigger undo command, which triggers re-creating widget (there even is no history to revert it).
So this simulation works as follows:

  1. Simulate keydown to register listeners on div by superflous function.
  2. Reload snapshot, to simulate Ctrl+Z, when previous snapshot is restored.
  3. Reloading snapshot automatically triggers re-creating widget. Here will be destroyed wrapping div for widget, and retain attribute will be lost (as it happens in Edge).
  4. Simulate keyup to execute proper listener from superflous function.

Re-loading snapshot might be replaced with some kind of triggering undo event, but it would require much more work. First to make some history, and then revert it. So I extract only important part from entire undo process, which is reloading snapshot, what cause the issue in case of using shortcut. This allows on proper simulation behaviour on Edge and proper fail of test in case of Edge environment without bug fix.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense 👍


editor.editable().fire( 'keyup', new CKEDITOR.dom.event( {} ) );

assert.areSame( 'div', editor.editable().getFirst().getName().toLowerCase() );
} );
}
} );
} )();
46 changes: 36 additions & 10 deletions tests/plugins/wysiwygarea/superfluouselement.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ bender.editor = {
};

bender.test( {
'Test removing superfluous <p> inserted by IE11': function() {
'test removing superfluous <p> inserted by IE11': function() {
if ( !CKEDITOR.env.ie || CKEDITOR.env.edge ) {
assert.ignore();
}
Expand Down Expand Up @@ -44,8 +44,8 @@ bender.test( {
wait();
},

'Test removing superfluous <div> inserted by Edge': function() {
if ( !CKEDITOR.env.edge ) {
'test removing superfluous <div> inserted by Edge': function() {
if ( !CKEDITOR.env.edge || CKEDITOR.env.version >= 15 ) {
assert.ignore();
}

Expand All @@ -70,8 +70,8 @@ bender.test( {
wait();
},

'Test not removing non-superfluous <div> in Edge': function() {
if ( !CKEDITOR.env.edge ) {
'test not removing non-superfluous <div> in Edge': function() {
if ( !CKEDITOR.env.edge || CKEDITOR.env.version >= 15 ) {
assert.ignore();
}

Expand All @@ -95,8 +95,8 @@ bender.test( {
wait();
},

'Test removing superfluous <div> when typing': function() {
if ( !CKEDITOR.env.edge ) {
'test removing superfluous <div> when typing in Edge': function() {
if ( !CKEDITOR.env.edge || CKEDITOR.env.version >= 15 ) {
assert.ignore();
}

Expand Down Expand Up @@ -145,8 +145,8 @@ bender.test( {
wait();
},

'Test not removing non-superfluous <div> when typing': function() {
if ( !CKEDITOR.env.edge ) {
'test not removing non-superfluous <div> when typing in Edge': function() {
if ( !CKEDITOR.env.edge || CKEDITOR.env.version >= 15 ) {
assert.ignore();
}

Expand Down Expand Up @@ -179,7 +179,7 @@ bender.test( {
},

// http://dev.ckeditor.com/ticket/14831
'Test not removing [data-cke-temp] <div> when typing': function() {
'test not removing [data-cke-temp] <div> when typing': function() {
if ( !CKEDITOR.env.edge || CKEDITOR.env.version < 14 ) {
assert.ignore();
}
Expand Down Expand Up @@ -227,5 +227,31 @@ bender.test( {
} );
} );
wait();
},

'test not removing <div> with any attributes in Edge': function() {
if ( !CKEDITOR.env.edge || CKEDITOR.env.version >= 15 ) {
assert.ignore();
}

var editor = this.editor;

editor.setData( '', function() {
resume( function() {

editor.editable().fire( 'keydown', new CKEDITOR.dom.event( {
keyCode: 75,
ctrlKey: false,
shiftKey: false
} ) );

bender.tools.setHtmlWithSelection( editor, '<div some="atribute">k^</div>' );

editor.editable().fire( 'keyup', new CKEDITOR.dom.event( {} ) );

assert.isInnerHtmlMatching( '<div some="atribute">k^</div>', bender.tools.getHtmlWithSelection( editor ) );
} );
} );
wait();
}
} );