Skip to content

Commit 7ffe649

Browse files
committed
Merge branch 't/11909'
2 parents c151a1b + 74ed892 commit 7ffe649

File tree

3 files changed

+128
-44
lines changed

3 files changed

+128
-44
lines changed

CHANGES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ Important Notes:
77

88
* We made CKEditor tests environment public. CKEditor tests can be found in the [`tests/`](https://github.com/ckeditor/ckeditor-dev/tree/master/tests) directory. Read more how to set up the environment and execute tests in the [CKEditor Tests Environment](http://docs.ckeditor.com/#!/guide/dev_tests) guide.
99

10+
New Features:
11+
12+
* [#11909](http://dev.ckeditor.com/ticket/11909): Introduced a parameter to prevent [`editor.setData()`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-method-setData) from recording undo snapshots.
13+
1014
Fixed Issues:
1115

1216
* [#11757](http://dev.ckeditor.com/ticket/11757): Fixed: Imperfections in the [Moono](http://ckeditor.com/addon/moono) skin. Thanks to [danyaPostfactum](https://github.com/danyaPostfactum)!

core/editor.js

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -926,20 +926,42 @@
926926
*
927927
* CKEDITOR.instances.editor1.setData( '<p>This is the editor data.</p>' );
928928
*
929-
* CKEDITOR.instances.editor1.setData( '<p>Some other editor data.</p>', function() {
930-
* this.checkDirty(); // true
931-
* });
932-
*
933-
* @param {String} data HTML code to replace the curent content in the editor.
934-
* @param {Function} callback Function to be called after the `setData` is completed.
935-
* @param {Boolean} internal Whether to suppress any event firing when copying data internally inside the editor.
929+
* CKEDITOR.instances.editor1.setData( '<p>Some other editor data.</p>', {
930+
* callback: function() {
931+
* this.checkDirty(); // true
932+
* }
933+
* } );
934+
*
935+
* Note: In CKEditor 4.4.2 the signature of this method has changed. All arguments
936+
* except `data` has been wrapped into the `options` object. However, backward compatibility
937+
* has been preserved and it is still possible to use the `data, callback, internal` arguments.
938+
*
939+
*
940+
* @param {String} data HTML code to replace the current content in the editor.
941+
* @param {Object} [options]
942+
* @param {Boolean} [options.internal=false] Whether to suppress any event firing when copying data internally inside the editor.
943+
* @param {Function} [options.callback] Function to be called after the `setData` is completed (on {@link #dataReady}).
944+
* @param {Boolean} [options.noSnapshot=false] If set to `true` will prevent recording undo snapshot.
945+
* Introduced in CKEditor 4.4.2.
936946
*/
937-
setData: function( data, callback, internal ) {
938-
!internal && this.fire( 'saveSnapshot' );
947+
setData: function( data, options, internal ) {
948+
var fireSnapshot = true,
949+
// Backward compatibility.
950+
callback = options,
951+
eventData;
952+
953+
if ( options && typeof options == 'object' ) {
954+
internal = options.internal;
955+
callback = options.callback;
956+
fireSnapshot = !options.noSnapshot;
957+
}
958+
959+
if ( !internal && fireSnapshot )
960+
this.fire( 'saveSnapshot' );
939961

940962
if ( callback || !internal ) {
941963
this.once( 'dataReady', function( evt ) {
942-
if ( !internal )
964+
if ( !internal && fireSnapshot )
943965
this.fire( 'saveSnapshot' );
944966

945967
if ( callback )
@@ -948,7 +970,7 @@
948970
}
949971

950972
// Fire "setData" so data manipulation may happen.
951-
var eventData = { dataValue: data };
973+
eventData = { dataValue: data };
952974
!internal && this.fire( 'setData', eventData );
953975

954976
this._.data = eventData.dataValue;

tests/core/editor/editor.js

Lines changed: 91 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -90,62 +90,120 @@ bender.test(
9090
/**
9191
* Test editor core data retrieval and manipulation functionality.
9292
*/
93-
test_getData : function() {
94-
var events = [];
93+
'test getData/setData': function() {
94+
var events = [],
95+
editor = new CKEDITOR.editor( {}, CKEDITOR.document.getById( 'editor4' ), CKEDITOR.ELEMENT_MODE_REPLACE );
9596
function checkEventData( value ) {
9697
return function( evt ) {
9798
events.push( evt.name );
98-
9999
// Check data value.
100100
if ( value )
101101
assert.areSame( value, evt.data.dataValue, 'check data on event: ' + evt.name );
102-
103102
// Alter the data value.
104103
if ( evt.name == 'setData' )
105104
evt.data.dataValue = 'bar';
106-
107105
};
108106
}
107+
// This function allows to call either older API or new object based setData().
108+
// It takes setData() params in new format (as editor#setData()).
109+
function callSetData( data, params, legacyInterface ) {
110+
if ( legacyInterface )
111+
editor.setData( data, params.callback, params.internal );
112+
else
113+
editor.setData( data, params );
114+
}
109115

110-
var editor =
111-
new CKEDITOR.editor( {},
112-
CKEDITOR.document.getById( 'editor4' ),
113-
CKEDITOR.ELEMENT_MODE_REPLACE );
114-
115-
// Events are fired on setData call.
116-
var checker = checkEventData();
116+
var listeners = [],
117+
allEvents = [ 'setData', 'afterSetData', 'beforeGetData', 'getData', 'saveSnapshot' ],
118+
listener = checkEventData();
117119

118-
var listeners = [];
119-
var allEvents = [ 'setData', 'afterSetData', 'beforeGetData', 'getData' ];
120120
for ( var i = 0; i < allEvents.length; i++ )
121-
listeners.push( editor.on( allEvents[ i ], checker ) );
121+
listeners.push( editor.on( allEvents[ i ], listener ) );
122122

123-
// Set/get data internally.
124-
editor.setData( 'foo', null, true );
125-
assert.areSame( 'foo', editor.getData( true ), 'setData internally' );
123+
for ( i = 0; i <= 1; i++ ) {
124+
var useOldAPI = Boolean( i ),
125+
// Helper var with human-readable info what interface version is called.
126+
interfaceName = useOldAPI ? 'old API params inline' :'new API params as object';
126127

127-
// No events should be fired.
128-
arrayAssert.itemsAreEqual( [], events );
128+
events = [];
129129

130-
for ( i = 0; i < listeners.length; i++ )
131-
listeners[ i ].removeListener();
130+
// Test setData/getData internal.
131+
callSetData( 'foo', { internal: true }, useOldAPI );
132+
assert.areSame( 'foo', editor.getData( true ), 'setData internally - ' + interfaceName );
133+
// No events should be fired.
134+
assert.areSame( '', events.join( ',' ), 'Events fired - ' + interfaceName );
132135

133-
// Events are fired on setData call.
134-
editor.on( 'setData', checkEventData( 'foo' ) );
135-
editor.on( 'afterSetData', checkEventData( 'bar' ) );
136-
editor.setData( 'foo' );
136+
events = [];
137+
// Test non-internal setData() - snapshot is expected.
138+
callSetData( 'foo', {}, useOldAPI );
137139

138-
arrayAssert.itemsAreEqual( [ 'setData', 'afterSetData' ], events );
139-
assert.areSame( 'bar', editor.getData(), 'setData listener change data value' );
140+
assert.areSame( 'saveSnapshot,setData,afterSetData', events.join( ',' ),
141+
'Invalid events for setData() - ' + interfaceName );
140142

143+
// Test non-internal getData().
144+
events = [];
145+
146+
assert.areSame( 'bar', editor.getData(), 'setData listener change data value - ' + interfaceName );
147+
assert.areSame( 'beforeGetData,getData', events.join( ',' ) );
148+
}
149+
150+
// New API provides params.noSnapshot, which should prevent saveSnapshot event.
141151
events = [];
142-
// Events are fired on getData call.
143-
editor.on( 'beforeGetData', checkEventData() );
144-
editor.on( 'getData', checkEventData( 'bar' ) );
145-
editor.getData();
152+
callSetData( 'foo', { noSnapshot: true } );
153+
154+
assert.areSame( 'setData,afterSetData', events.join( ',' ), 'Invalid events with params.noSnapshot = true' );
155+
},
156+
157+
'test setData callback': function() {
158+
var callbackCalledTimes = 0,
159+
callback = function() {
160+
callbackCalledTimes += 1;
161+
},
162+
waitTimeout = 80;
163+
164+
this.editor.setData( '<p>setData</p>', { callback: callback } );
165+
166+
wait( function() {
167+
assert.areEqual( 1, callbackCalledTimes, 'Invalid callback calls count' );
168+
// And test for older API.
169+
this.editor.setData( '<p>setData</p>', callback );
170+
171+
wait( function() {
172+
assert.areEqual( 2, callbackCalledTimes, 'Invalid callback calls count 2nd case' );
173+
}, waitTimeout );
174+
}, waitTimeout );
175+
},
176+
177+
'test setData()': function() {
178+
var firedEvents = [],
179+
listeners = [],
180+
editor = this.editor,
181+
subscribedEvents = [ 'setData', 'afterSetData', 'beforeGetData', 'getData' ],
182+
callbackCalledTimes = 0,
183+
callback = function() {
184+
callbackCalledTimes += 1;
185+
},
186+
// This listener will store types of events fired.
187+
listener = function( evt ) {
188+
firedEvents.push( evt.name );
189+
};
190+
191+
// Registering listeners.
192+
for ( var i = 0; i < subscribedEvents.length; i++ )
193+
listeners.push( editor.on( subscribedEvents[ i ], listener ) );
194+
195+
// Legacy interface.
196+
editor.setData( '<p>setData</p>', null, true );
197+
arrayAssert.itemsAreEqual( [], firedEvents );
198+
199+
assert.areEqual( '<p>setData</p>', editor.getData( true ) );
200+
arrayAssert.itemsAreEqual( [], firedEvents );
146201

147-
arrayAssert.itemsAreEqual( [ 'beforeGetData', 'getData' ], events );
202+
assert.isTrue( true );
148203

204+
// Cleanup.
205+
for ( var i = 0; i < listeners.length; i++ )
206+
listeners[ i ].removeListener();
149207
},
150208

151209
updateElement: function( element, mode ) {

0 commit comments

Comments
 (0)