diff --git a/CHANGES.md b/CHANGES.md index dbd3480255e..64cecdde1e7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,6 +5,8 @@ CKEditor 4 Changelog New Features: +* [#4461](https://github.com/ckeditor/ckeditor4/issues/4461): Introduced possibility to delay editor initialization while it is in detached DOM element. + Fixed Issues: * [#4604](https://github.com/ckeditor/ckeditor4/issues/4604): Fixed: [`CKEDITOR.plugins.clipboard.dataTransfer#getTypes()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_clipboard_dataTransfer.html#method-getTypes) returns no types. diff --git a/core/creators/inline.js b/core/creators/inline.js index 7321e531b3d..862d935389f 100644 --- a/core/creators/inline.js +++ b/core/creators/inline.js @@ -35,11 +35,18 @@ return null; } - var editor = new CKEDITOR.editor( instanceConfig, element, CKEDITOR.ELEMENT_MODE_INLINE ), - textarea = element.is( 'textarea' ) ? element : null; + // (#4461) + if ( CKEDITOR.editor.shouldDelayEditorCreation( element, instanceConfig ) ) { + CKEDITOR.editor.initializeDelayedEditorCreation( element, instanceConfig, 'inline' ); + return null; + } + + var textarea = element.is( 'textarea' ) ? element : null, + editorData = textarea ? textarea.getValue() : element.getHtml(), + editor = new CKEDITOR.editor( instanceConfig, element, CKEDITOR.ELEMENT_MODE_INLINE ); if ( textarea ) { - editor.setData( textarea.getValue(), null, true ); + editor.setData( editorData, null, true ); //Change element from textarea to div element = CKEDITOR.dom.element.createFromHtml( @@ -63,7 +70,7 @@ // Initial editor data is simply loaded from the page element content to make // data retrieval possible immediately after the editor creation. - editor.setData( element.getHtml(), null, true ); + editor.setData( editorData, null, true ); } // Once the editor is loaded, start the UI. @@ -156,6 +163,7 @@ CKEDITOR.domReady( function() { !CKEDITOR.disableAutoInline && CKEDITOR.inlineAll(); } ); + } )(); /** diff --git a/core/creators/themedui.js b/core/creators/themedui.js index 94f64f1b553..4df16f428b2 100644 --- a/core/creators/themedui.js +++ b/core/creators/themedui.js @@ -343,6 +343,12 @@ CKEDITOR.replaceClass = 'ckeditor'; return null; } + // (#4461) + if ( CKEDITOR.editor.shouldDelayEditorCreation( element, config ) ) { + CKEDITOR.editor.initializeDelayedEditorCreation( element, config, 'replace' ); + return null; + } + // Create the editor instance. var editor = new CKEDITOR.editor( config, element, mode ); diff --git a/core/editor.js b/core/editor.js index 72567c3b17a..26a868ec64e 100644 --- a/core/editor.js +++ b/core/editor.js @@ -1648,6 +1648,103 @@ return element; }; + + /** + * Initializes delayed editor creation based on provided configuration. + * + * If the {@link CKEDITOR.config#delayIfDetached_callback} function is declared, it will be invoked with a single argument: + * + * * A callback, that should be called to create editor. + * + * Otherwise, it periodically (with `setInterval()` calls) checks if element is attached to DOM and creates editor automatically. + * + * ```js + * CKEDITOR.inline( detachedEditorElement, { + * delayIfDetached: true, + * delayIfDetached_callback: registerCallback + * } ); + * ``` + * + * @private + * @since 4.17.0 + * @static + * @member CKEDITOR.editor + * @param {CKEDITOR.dom.element} element The DOM element on which editor should be initialized. + * @param {Object} config The specific configuration to apply to the editor instance. Configuration set here will override the global CKEditor settings. + * @param {String} editorCreationMethod Creator function that should be used to initialize editor (inline/replace). + */ + CKEDITOR.editor.initializeDelayedEditorCreation = function( element, config, editorCreationMethod ) { + if ( config.delayIfDetached_callback ) { + CKEDITOR.warn( 'editor-delayed-creation', { + method: 'callback' + } ); + + config.delayIfDetached_callback( function() { + CKEDITOR[ editorCreationMethod ]( element, config ); + + CKEDITOR.warn( 'editor-delayed-creation-success', { + method: 'callback' + } ); + } ); + } else { + var interval = config.delayIfDetached_interval === undefined ? CKEDITOR.config.delayIfDetached_interval : config.delayIfDetached_interval, + intervalId; + + CKEDITOR.warn( 'editor-delayed-creation', { + method: 'interval - ' + interval + ' ms' + } ); + + intervalId = setInterval( function() { + if ( !element.isDetached() ) { + clearInterval( intervalId ); + + CKEDITOR[ editorCreationMethod ]( element, config ); + + CKEDITOR.warn( 'editor-delayed-creation-success', { + method: 'interval - ' + interval + ' ms' + } ); + } + }, interval ); + } + }; + + /** + * Whether editor creation should be delayed. + * + * @private + * @since 4.17.0 + * @static + * @member CKEDITOR.editor + * @param {CKEDITOR.dom.element} element The DOM element on which editor should be initialized. + * @param {Object} config Editor configuration. + * @returns {Boolean} True if creation should be delayed. + */ + CKEDITOR.editor.shouldDelayEditorCreation = function( element, config ) { + CKEDITOR.editor.mergeDelayedCreationConfigs( config ); + return config && config.delayIfDetached && element.isDetached(); + }; + + /** + * Merges user provided configuration options for delayed creation with {@link CKEDITOR.config default config}. + * + * User provided options are the preferred ones. + * + * @private + * @since 4.17.0 + * @static + * @member CKEDITOR.editor + * @param {Object} userConfig Config provided by the user to create editor. + */ + CKEDITOR.editor.mergeDelayedCreationConfigs = function( userConfig ) { + if ( !userConfig ) { + return; + } + + userConfig.delayIfDetached = typeof userConfig.delayIfDetached === 'boolean' ? userConfig.delayIfDetached : CKEDITOR.config.delayIfDetached; + userConfig.delayIfDetached_interval = isNaN( userConfig.delayIfDetached_interval ) ? CKEDITOR.config.delayIfDetached_interval : userConfig.delayIfDetached_interval; + userConfig.delayIfDetached_callback = userConfig.delayIfDetached_callback || CKEDITOR.config.delayIfDetached_callback; + }; + } )(); /** @@ -2228,3 +2325,61 @@ CKEDITOR.ELEMENT_MODE_INLINE = 3; * @event contentDomInvalidated * @param {CKEDITOR.editor} editor This editor instance. */ + +/** + * If set to `true`, editor will be only created when its root element is attached to DOM. + * In case the element is detached, the editor will wait for the element to be attached and initialized then. + * + * For more control over the entire process refer to {@link CKEDITOR.config#delayIfDetached_callback} + * and {@link CKEDITOR.config#delayIfDetached_interval} configuration options. + * + * config.delayIfDetached = true; + * + * @since 4.17.0 + * @cfg {Boolean} [delayIfDetached=false] + * @member CKEDITOR.config + */ +CKEDITOR.config.delayIfDetached = false; + +/** + * Function used to initialize delayed editor creation. + * + * It accepts a single `callback` argument. A `callback` argument is another function that triggers editor creation. + * This allows to store the editor creation function (`callback`) and invoke it whenever necessary instead of periodically + * check if element is attached to DOM to improve performance. + * + * Used only if {@link CKEDITOR.config#delayIfDetached} is set to `true`. + * + * **Note**: This function (`callback`) should be called only if editor target element is reattached to DOM. + * + * If this option is defined, editor will not run the default {@link CKEDITOR.config#delayIfDetached_interval interval checks}. + * + * // Store the reference to the editor creation function. + * var resumeEditorCreation; + * + * config.delayIfDetached_callback = function( createEditor ) { + * resumeEditorCreation = createEditor; + * }; + * + * // Create editor calling `resumeEditorCreation()` whenever you choose (e.g. on button click). + * resumeEditorCreation(); + * + * @since 4.17.0 + * @cfg {Function} [delayIfDetached_callback = undefined] + * @member CKEDITOR.config + */ +CKEDITOR.config.delayIfDetached_callback = undefined; + +/** + * The amount of time (in milliseconds) between consecutive checks whether editor's target element is attached to DOM. + * + * Used only if {@link CKEDITOR.config#delayIfDetached} is set to `true` and + * {@link CKEDITOR.config#delayIfDetached_callback delayIfDetached_callback} not set. + * + * config.delayIfDetached_interval = 2000; // Try to create editor every 2 seconds. + * + * @since 4.17.0 + * @cfg {Number} [delayIfDetached_interval=50] + * @member CKEDITOR.config + */ +CKEDITOR.config.delayIfDetached_interval = 50; diff --git a/tests/core/creators/_helpers/tools.js b/tests/core/creators/_helpers/tools.js new file mode 100644 index 00000000000..f65350ed629 --- /dev/null +++ b/tests/core/creators/_helpers/tools.js @@ -0,0 +1,240 @@ +/* exported detachedTests */ + +'use strict'; + +var detachedTests = ( function() { + function appendTests( creatorFunction, tests ) { + + return CKEDITOR.tools.extend( tests, { + test_editor_is_created_immediately_on_not_detached_element_even_with_delay_config: function() { + var editorElement = CKEDITOR.document.getById( createHtmlForEditor() ), + editor = CKEDITOR[ creatorFunction ]( editorElement, { + delayIfDetached: true, + delayIfDetached_callback: function() {} + } ); + + assert.isNotNull( editor, 'Editor should be created immediately on not detached element, even if config allows a delay. Creator function used: ' + creatorFunction ); + }, + + test_editor_is_created_immediately_on_not_detached_element_with_delayIfDetached_config_set_as_false: function() { + var editorElement = CKEDITOR.document.getById( createHtmlForEditor() ), + editor = CKEDITOR[ creatorFunction ]( editorElement, { + delayIfDetached: false + } ); + + assert.isNotNull( editor, 'Editor should be created immediately on not detached element, despite config delay option. Creator function used: ' + creatorFunction ); + }, + + test_editor_without_config_is_created_immediately_on_not_detached_element: function() { + var editorElement = CKEDITOR.document.getById( createHtmlForEditor() ), + editor = CKEDITOR[ creatorFunction ]( editorElement ); + + assert.isNotNull( editor, 'Editor should be created immediately with default config options. Creator function used: ' + creatorFunction ); + }, + + test_delay_editor_creation_if_target_element_is_detached: function() { + var editorElement = CKEDITOR.document.getById( createHtmlForEditor() ), + editorParent = editorElement.getParent(); + + editorElement.remove(); + + var editor = CKEDITOR[ creatorFunction ]( editorElement, { + delayIfDetached: true + } ); + + assert.isNull( editor, 'Editor should not be created on detached element, if config allows a delay. Creator function used: ' + creatorFunction ); + + editorParent.append( editorElement ); + }, + + test_delay_editor_creation_with_default_interval_strategy_until_target_element_attach_to_DOM: function() { + var editorElement = CKEDITOR.document.getById( createHtmlForEditor() ), + editorParent = editorElement.getParent(); + + editorElement.remove(); + + CKEDITOR[ creatorFunction ]( editorElement, { + delayIfDetached: true, + on: { + instanceReady: function() { + resume( function() { + assert.pass( 'Editor was created. Creator function used: ' + creatorFunction ); + } ); + } + } + } ); + + CKEDITOR.tools.setTimeout( function() { + editorParent.append( editorElement ); + }, 250 ); + + wait(); + }, + + test_editor_creation_from_provided_callback: function() { + var editorElement = CKEDITOR.document.getById( createHtmlForEditor() ), + editorParent = editorElement.getParent(), + editorCreationCallback; + + editorElement.remove(); + + CKEDITOR[ creatorFunction ]( editorElement, { + delayIfDetached: true, + delayIfDetached_callback: registerCallback, + on: { + instanceReady: function() { + resume( function() { + assert.pass( 'Editor was created from custom callback. Creator function used: ' + creatorFunction ); + } ); + } + } + } ); + + function registerCallback( editorCreationFunc ) { + editorCreationCallback = editorCreationFunc; + } + + CKEDITOR.tools.setTimeout( function() { + editorParent.append( editorElement ); + editorCreationCallback(); + }, 250 ); + + wait(); + }, + + test_editor_default_delay_creation_invokes_CKEDITOR_warn: function() { + var spyWarn = sinon.spy(), + editorElement = CKEDITOR.document.getById( createHtmlForEditor() ), + editorParent = editorElement.getParent(); + + editorElement.remove(); + + CKEDITOR.on( 'log', spyWarn ); + + CKEDITOR[ creatorFunction ]( editorElement, { + delayIfDetached: true, + on: { + instanceReady: function() { + resume( function() { + var firstCallData = spyWarn.firstCall.args[ 0 ].data, + secondCallData = spyWarn.secondCall.args[ 0 ].data, + expectedMethod = 'interval - ' + CKEDITOR.config.delayIfDetached_interval + ' ms'; + + assert.areEqual( 'editor-delayed-creation', firstCallData.errorCode, 'First editor warn should be about creation delay with interval. Creator function used: ' + creatorFunction ); + assert.areEqual( expectedMethod , firstCallData.additionalData.method, 'First editor warn method should be interval with time. Creator function used: ' + creatorFunction ); + + assert.areEqual( + 'editor-delayed-creation-success', + secondCallData.errorCode, + 'Second editor warn should be about success editor creation with interval. Creator function used: ' + creatorFunction + ); + assert.areEqual( + expectedMethod, + secondCallData.additionalData.method, + 'Second editor warn method should be interval with time. Creator function used: ' + creatorFunction + ); + + CKEDITOR.removeListener( 'log', spyWarn ); + } ); + } + } + } ); + + CKEDITOR.tools.setTimeout( function() { + editorParent.append( editorElement ); + }, 250 ); + + wait(); + }, + + test_editor_delay_creation_with_callback_invokes_CKEDITOR_warn: function() { + var spyWarn = sinon.spy(), + editorElement = CKEDITOR.document.getById( createHtmlForEditor() ), + editorParent = editorElement.getParent(), + resumeEditorCreation; + + editorElement.remove(); + + CKEDITOR.on( 'log', spyWarn ); + + function delayedCallback( createEditorFunction ) { + resumeEditorCreation = createEditorFunction; + } + + CKEDITOR[ creatorFunction ]( editorElement, { + delayIfDetached: true, + delayIfDetached_callback: delayedCallback, + on: { + instanceReady: function() { + resume( function() { + var firstCallData = spyWarn.firstCall.args[ 0 ].data, + secondCallData = spyWarn.secondCall.args[ 0 ].data; + + assert.areEqual( 'editor-delayed-creation', firstCallData.errorCode, 'First editor warn should be about creation delay with callback. Creator function used: ' + creatorFunction ); + assert.areEqual( 'callback' , firstCallData.additionalData.method, 'First editor warn method should be \'callback\'. Creator function used: ' + creatorFunction ); + + assert.areEqual( + 'editor-delayed-creation-success', + secondCallData.errorCode, + 'Second editor warn should be about success editor creation with callback. Creator function used: ' + creatorFunction + ); + assert.areEqual( + 'callback', + secondCallData.additionalData.method, + 'Second editor warn method should be \'callback\'. Creator function used: ' + creatorFunction + ); + + CKEDITOR.removeListener( 'log', spyWarn ); + } ); + } + } + } ); + + CKEDITOR.tools.setTimeout( function() { + editorParent.append( editorElement ); + + resumeEditorCreation(); + }, 250 ); + + wait(); + }, + + test_editor_interval_attempts_to_create_if_target_element_is_detached: function() { + var editorElement = CKEDITOR.document.getById( createHtmlForEditor() ), + editorElementParent = editorElement.getParent(), + spyIsDetached = sinon.spy( editorElement, 'isDetached' ); + + editorElement.remove(); + + CKEDITOR[ creatorFunction ]( editorElement, { + delayIfDetached: true, + delayIfDetached_interval: 50 + } ); + + CKEDITOR.tools.setTimeout( function() { + resume( function() { + editorElementParent.append( editorElement ); + assert.isTrue( spyIsDetached.callCount > 2, 'There should be at least three calls of isDetached(). Creator function used: ' + creatorFunction ); + spyIsDetached.restore(); + } ); + }, 200 ); + + wait(); + } + } ); + } + + function createHtmlForEditor() { + var editorId = 'editor' + new Date().getTime(), + editorSlot = CKEDITOR.dom.element.createFromHtml( '

Content!!

' ); + + CKEDITOR.document.getBody().append( editorSlot ); + + return editorId; + } + + return { + appendTests: appendTests + }; + +} )(); diff --git a/tests/core/creators/detachedappendto.js b/tests/core/creators/detachedappendto.js new file mode 100644 index 00000000000..713753fa7e2 --- /dev/null +++ b/tests/core/creators/detachedappendto.js @@ -0,0 +1,13 @@ +/* bender-tags: editor, feature, 4461 */ +/* bender-ckeditor-plugins: wysiwygarea */ + +/* bender-include: _helpers/tools.js */ +/* global detachedTests */ + +( function() { + 'use strict'; + + var tests = detachedTests.appendTests( 'appendTo', {} ); + + bender.test( tests ); +}() ); diff --git a/tests/core/creators/detachedinline.html b/tests/core/creators/detachedinline.html new file mode 100644 index 00000000000..edc6095c669 --- /dev/null +++ b/tests/core/creators/detachedinline.html @@ -0,0 +1,4 @@ +
+
+
+
diff --git a/tests/core/creators/detachedinline.js b/tests/core/creators/detachedinline.js new file mode 100644 index 00000000000..6396c0fb715 --- /dev/null +++ b/tests/core/creators/detachedinline.js @@ -0,0 +1,35 @@ +/* bender-tags: editor, feature, 4461 */ +/* bender-ckeditor-plugins: floatingspace,toolbar,font */ + +/* bender-include: _helpers/tools.js */ +/* global detachedTests */ + +( function() { + 'use strict'; + + var tests = detachedTests.appendTests( 'inline', { + 'test CKEDITOR.inlineAll() doesnt call the shouldDelayEditorCreation() function when elements are detached': function() { + var inlineSpy = sinon.spy( CKEDITOR.editor, 'shouldDelayEditorCreation' ), + editableParent = CKEDITOR.document.getById( 'inlineEditableParent' ); + + editableParent.remove(); + CKEDITOR.on( 'inline', bindToInline, null, null, 0 ); + CKEDITOR.inlineAll(); + + assert.areEqual( 0, inlineSpy.callCount, 'There should be no CKEDITOR.editor.shouldDelayEditorCreation() calls.' ); + + inlineSpy.restore(); + CKEDITOR.removeListener( 'inline' , bindToInline ); + } + } ); + + bender.test( tests ); + + function bindToInline( evt ) { + evt && evt.removeListener(); + + evt.data.config = { + delayIfDetached: true + }; + } +}() ); diff --git a/tests/core/creators/detachedreplace.html b/tests/core/creators/detachedreplace.html new file mode 100644 index 00000000000..4b06787c674 --- /dev/null +++ b/tests/core/creators/detachedreplace.html @@ -0,0 +1,3 @@ +
+ +
diff --git a/tests/core/creators/detachedreplace.js b/tests/core/creators/detachedreplace.js new file mode 100644 index 00000000000..60668fa3516 --- /dev/null +++ b/tests/core/creators/detachedreplace.js @@ -0,0 +1,25 @@ +/* bender-tags: editor, feature, 4461 */ +/* bender-ckeditor-plugins: wysiwygarea */ + +/* bender-include: _helpers/tools.js */ +/* global detachedTests */ + +( function() { + 'use strict'; + + var tests = detachedTests.appendTests( 'replace', { + 'test CKEDITOR.replaceAll() doesnt call the shouldDelayEditorCreation() function when elements are detached': function() { + var textarea = CKEDITOR.document.getById( 'ta1' ), + replaceSpy = sinon.spy( CKEDITOR.editor, 'shouldDelayEditorCreation' ); + + textarea.remove(); + CKEDITOR.replaceAll(); + + assert.areEqual( 0, replaceSpy.callCount, 'There should be no CKEDITOR.replace calls.' ); + + replaceSpy.restore(); + } + } ); + + bender.test( tests ); +}() ); diff --git a/tests/core/creators/manual/detachedcustomcallback.html b/tests/core/creators/manual/detachedcustomcallback.html new file mode 100644 index 00000000000..1c17f9e9dfa --- /dev/null +++ b/tests/core/creators/manual/detachedcustomcallback.html @@ -0,0 +1,38 @@ + + + +
+
+

Lorem ipsum dolor sit amet.

+
+
+ + diff --git a/tests/core/creators/manual/detachedcustomcallback.md b/tests/core/creators/manual/detachedcustomcallback.md new file mode 100644 index 00000000000..ea10bd0466f --- /dev/null +++ b/tests/core/creators/manual/detachedcustomcallback.md @@ -0,0 +1,26 @@ +@bender-tags: 4.17.0, feature, 4461 +@bender-ui: collapsed +@bender-ckeditor-plugins: toolbar, wysiwygarea, sourcearea, undo, clipboard, basicstyles, elementspath + +1. Open developer console. +2. Click `Try to create editor` button. + + **Expected** + * `editor-delayed-creation` warning with `{ method: callback }` object showed up in the console. **On IE8-11 you'll get `[object Object]` instead.** + + **Unexpected** + * No `editor-delayed-creation` warning in the console. + +3. Click second button to attach editor to DOM element and invoke config callback to finish editor creation. + + **Expected** + * `editor-delayed-creation-success` warning with `{ method: callback }` object showed up in the console. **On IE8-11 you'll get `[object Object]` instead.** + * Editor is created. + * Editor contains initial data. + * Editor data is editable. + + **Unexpected** + * No `editor-delayed-creation-success` warning in the console. + * Editor isn't created. + * Editor data is empty. + * Editor data is not editable. diff --git a/tests/core/creators/manual/detachedcustomcallbackmobile.html b/tests/core/creators/manual/detachedcustomcallbackmobile.html new file mode 100644 index 00000000000..8601c24dabc --- /dev/null +++ b/tests/core/creators/manual/detachedcustomcallbackmobile.html @@ -0,0 +1,49 @@ +
+ + +
+
+

Lorem ipsum dolor sit amet.

+
+
+ + diff --git a/tests/core/creators/manual/detachedcustomcallbackmobile.md b/tests/core/creators/manual/detachedcustomcallbackmobile.md new file mode 100644 index 00000000000..1b5ac5d8ae5 --- /dev/null +++ b/tests/core/creators/manual/detachedcustomcallbackmobile.md @@ -0,0 +1,16 @@ +@bender-tags: 4.17.0, feature, 4461 +@bender-ui: collapsed +@bender-ckeditor-plugins: toolbar, wysiwygarea, sourcearea, undo, clipboard, basicstyles, elementspath + +1. Click `Try to create editor` button. +2. Click the second button to attach editor to DOM element and invoke config callback to finish editor creation. + + **Expected** + * Editor is created. + * Editor contains initial data. + * Editor data is editable. + + **Unexpected** + * Editor isn't created. + * Editor data is empty. + * Editor data is not editable. diff --git a/tests/core/creators/manual/detachedcustominterval.html b/tests/core/creators/manual/detachedcustominterval.html new file mode 100644 index 00000000000..47d6751332f --- /dev/null +++ b/tests/core/creators/manual/detachedcustominterval.html @@ -0,0 +1,47 @@ + + + +
+
+

Lorem ipsum dolor sit amet.

+
+
+ + diff --git a/tests/core/creators/manual/detachedcustominterval.md b/tests/core/creators/manual/detachedcustominterval.md new file mode 100644 index 00000000000..9e675844626 --- /dev/null +++ b/tests/core/creators/manual/detachedcustominterval.md @@ -0,0 +1,26 @@ +@bender-tags: 4.17.0, feature, 4461 +@bender-ui: collapsed +@bender-ckeditor-plugins: toolbar, wysiwygarea, sourcearea, undo, clipboard, basicstyles, elementspath + +1. Open developer console. Watch for editor warning, right after button click in next step. +2. Click the button to start the test. + + **Expected** + * `editor-delayed-creation` warning with `{ method: interval - 3000 ms }` object showed in the console. **On IE8-11 you'll get `[object Object]` instead.** + + **Unexpected** + * No `editor-delayed-creation` warning in the console. + +3. Wait three seconds for editor creation. + + **Expected** + * `editor-delayed-creation-success` warning with `{ method: interval - 3000 ms }` object showed in the console. **On IE8-11 you'll get `[object Object]` instead.** + * Editor is created. + * Editor contains initial data. + * Editor data is editable. + + **Unexpected** + * No `editor-delayed-creation-success` warning in the console. + * Editor isn't created. + * Editor data is empty. + * Editor data is not editable. diff --git a/tests/core/creators/manual/detachedcustomintervalmobile.html b/tests/core/creators/manual/detachedcustomintervalmobile.html new file mode 100644 index 00000000000..c981f286d42 --- /dev/null +++ b/tests/core/creators/manual/detachedcustomintervalmobile.html @@ -0,0 +1,56 @@ +
+ + + +
+
+

Lorem ipsum dolor sit amet.

+
+
+ + diff --git a/tests/core/creators/manual/detachedcustomintervalmobile.md b/tests/core/creators/manual/detachedcustomintervalmobile.md new file mode 100644 index 00000000000..a9d7a155c62 --- /dev/null +++ b/tests/core/creators/manual/detachedcustomintervalmobile.md @@ -0,0 +1,16 @@ +@bender-tags: 4.17.0, feature, 4461 +@bender-ui: collapsed +@bender-ckeditor-plugins: toolbar, wysiwygarea, sourcearea, undo, clipboard, basicstyles, elementspath + +1. Click the button to start the test. +2. Wait three seconds for editor creation. + + **Expected** + * Editor is created. + * Editor contains initial data. + * Editor data is editable. + + **Unexpected** + * Editor isn't created. + * Editor data is empty. + * Editor data is not editable. diff --git a/tests/core/creators/manual/detacheddefault.html b/tests/core/creators/manual/detacheddefault.html new file mode 100644 index 00000000000..336167d12d8 --- /dev/null +++ b/tests/core/creators/manual/detacheddefault.html @@ -0,0 +1,23 @@ + + +
+
+

Lorem ipsum dolor sit amet.

+
+
+ + diff --git a/tests/core/creators/manual/detacheddefault.md b/tests/core/creators/manual/detacheddefault.md new file mode 100644 index 00000000000..71b398d2ccd --- /dev/null +++ b/tests/core/creators/manual/detacheddefault.md @@ -0,0 +1,15 @@ +@bender-tags: 4.17.0, feature, 4461 +@bender-ui: collapsed +@bender-ckeditor-plugins: toolbar, wysiwygarea, sourcearea, undo, clipboard, basicstyles, elementspath + +1. Click button to attach editor to DOM element. + + **Expected** + * Editor is created. + * Editor contains initial data. + * Editor data is editable. + + **Unexpected** + * Editor isn't created. + * Editor data is empty. + * Editor data is not editable. diff --git a/tests/plugins/widget/insertparagraphnexttowidget.js b/tests/plugins/widget/insertparagraphnexttowidget.js index ae6e1b88364..efb3558cd82 100644 --- a/tests/plugins/widget/insertparagraphnexttowidget.js +++ b/tests/plugins/widget/insertparagraphnexttowidget.js @@ -23,6 +23,12 @@ bogusDiv = '
 
'; bender.test( { + _should: { + ignore: { + // #4563 + 'test press shift + enter with ckeditor.enter_br inserts
element after a widget': bender.env.ie && bender.env.version == '8' + } + }, // (#4467) 'test press shift + alt + enter must insert a paragraph before a widget': testFactory( {