Skip to content
Snippets Groups Projects
Unverified Commit eddae137 authored by Lauri Timmanee's avatar Lauri Timmanee
Browse files

Issue #3241295 by mherchel, glynster, _utsavsharma, Emil Stoianov, rkoller,...

Issue #3241295 by mherchel, glynster, _utsavsharma, Emil Stoianov, rkoller, Wim Leers, gaurav-mathur, DeepaliJ, geek-merlin, tgoeg, ckrina, mgifford, zcht, Dom., smustgrave, nod_, mstrelan, RgnYLDZ: CKEditor 5 isn't respecting field widgets row settings
parent 0498fbfc
No related branches found
No related tags found
32 merge requests!7452Issue #1797438. HTML5 validation is preventing form submit and not fully...,!54479.5.x SF update,!5014Issue #3071143: Table Render Array Example Is Incorrect,!4868Issue #1428520: Improve menu parent link selection,!4289Issue #1344552 by marcingy, Niklas Fiekas, Ravi.J, aleevas, Eduardo Morales...,!4114Issue #2707291: Disable body-level scrolling when a dialog is open as a modal,!4100Issue #3249600: Add support for PHP 8.1 Enums as allowed values for list_* data types,!3630Issue #2815301 by Chi, DanielVeza, kostyashupenko, smustgrave: Allow to create...,!3600Issue #3344629: Passing null to parameter #1 ($haystack) of type string is deprecated,!3291Issue #3336463: Rewrite rules for gzipped CSS and JavaScript aggregates never match,!2378Issue #2875033: Optimize joins and table selection in SQL entity query implementation,!2334Issue #3228209: Add hasRole() method to AccountInterface,!2074Issue #2707689: NodeForm::actions() checks for delete access on new entities,!2062Issue #3246454: Add weekly granularity to views date sort,!1591Issue #3199697: Add JSON:API Translation experimental module,!1484Exposed filters get values from URL when Ajax is on,!1255Issue #3238922: Refactor (if feasible) uses of the jQuery serialize function to use vanillaJS,!1162Issue #3100350: Unable to save '/' root path alias,!1105Issue #3025039: New non translatable field on translatable content throws error,!1073issue #3191727: Focus states on mobile second level navigation items fixed,!10223132456: Fix issue where views instances are emptied before an ajax request is complete,!957Added throwing of InvalidPluginDefinitionException from getDefinition().,!925Issue #2339235: Remove taxonomy hard dependency on node module,!877Issue #2708101: Default value for link text is not saved,!872Draft: Issue #3221319: Race condition when creating menu links and editing content deletes menu links,!844Resolve #3036010 "Updaters",!617Issue #3043725: Provide a Entity Handler for user cancelation,!579Issue #2230909: Simple decimals fail to pass validation,!560Move callback classRemove outside of the loop,!555Issue #3202493,!485Sets the autocomplete attribute for username/password input field on login form.,!30Issue #3182188: Updates composer usage to point at ./vendor/bin/composer
...@@ -1101,6 +1101,7 @@ someschema ...@@ -1101,6 +1101,7 @@ someschema
somethinggeneric somethinggeneric
sortablejs sortablejs
sourcedir sourcedir
sourceediting
spacebar spacebar
spagna spagna
specialchars specialchars
......
...@@ -8,3 +8,14 @@ ...@@ -8,3 +8,14 @@
opacity: 1 !important; opacity: 1 !important;
fill-opacity: 1 !important; fill-opacity: 1 !important;
} }
/**
* Set the min-height equal to configuration value for the number of rows.
*
* The `--ck-min-height` value is set on the parent `.ck-editor` element by
* JavaScript. We add that there because the `.ck-editor__editable` element's
* inline styles are cleared on focus.
*/
.ck-editor__main > :is(.ck-editor__editable, .ck-source-editing-area) {
min-height: var(--ck-min-height);
}
...@@ -370,9 +370,55 @@ ...@@ -370,9 +370,55 @@
ClassicEditor.create(element, editorConfig) ClassicEditor.create(element, editorConfig)
.then((editor) => { .then((editor) => {
/**
* Injects a temporary <p> into CKEditor and then calculates the entire
* height of the amount of the <p> tags from the passed in rows value.
*
* This takes into account collapsing margins, and line-height of the
* current theme.
*
* @param {number} - the number of rows.
*
* @returns {number} - the height of a div in pixels.
*/
function calculateLineHeight(rows) {
const element = document.createElement('p');
element.setAttribute('style', 'visibility: hidden;');
element.innerHTML = '&nbsp;';
editor.ui.view.editable.element.append(element);
const styles = window.getComputedStyle(element);
const height = element.clientHeight;
const marginTop = parseInt(styles.marginTop, 10);
const marginBottom = parseInt(styles.marginBottom, 10);
const mostMargin =
marginTop >= marginBottom ? marginTop : marginBottom;
element.remove();
return (
(height + mostMargin) * (rows - 1) +
marginTop +
height +
marginBottom
);
}
// Save a reference to the initialized instance. // Save a reference to the initialized instance.
Drupal.CKEditor5Instances.set(id, editor); Drupal.CKEditor5Instances.set(id, editor);
// Set the minimum height of the editable area to correspond with the
// value of the number of rows. We attach this custom property to
// the `.ck-editor` element, as that doesn't get its inline styles
// cleared on focus. The editable element is then set to use this
// property within the stylesheet.
const rows = editor.sourceElement.getAttribute('rows');
editor.ui.view.editable.element
.closest('.ck-editor')
.style.setProperty(
'--ck-min-height',
`${calculateLineHeight(rows)}px`,
);
// CKEditor 4 had a feature to remove the required attribute // CKEditor 4 had a feature to remove the required attribute
// see: https://www.drupal.org/project/drupal/issues/1954968 // see: https://www.drupal.org/project/drupal/issues/1954968
if (element.hasAttribute('required')) { if (element.hasAttribute('required')) {
......
module.exports = {
'@tags': ['core', 'ckeditor5'],
before(browser) {
browser.drupalInstall({ installProfile: 'minimal' });
},
after(browser) {
browser.drupalUninstall();
},
'Ensure CKEditor respects field widget row value': (browser) => {
browser.drupalLoginAsAdmin(() => {
browser
// Enable required modules.
.drupalRelativeURL('/admin/modules')
.click('[name="modules[ckeditor5][enable]"]')
.click('[name="modules[field_ui][enable]"]')
.submitForm('input[type="submit"]') // Submit module form.
.waitForElementVisible(
'.system-modules-confirm-form input[value="Continue"]',
)
.submitForm('input[value="Continue"]') // Confirm installation of dependencies.
.waitForElementVisible('.system-modules', 10000)
// Create new input format.
.drupalRelativeURL('/admin/config/content/formats/add')
.waitForElementVisible('[data-drupal-selector="edit-name"]')
.updateValue('[data-drupal-selector="edit-name"]', 'test')
.waitForElementVisible('#edit-name-machine-name-suffix')
.click(
'[data-drupal-selector="edit-editor-editor"] option[value=ckeditor5]',
)
// Wait for CKEditor 5 settings to be visible.
.waitForElementVisible(
'[data-drupal-selector="edit-editor-settings-toolbar"]',
)
.click('.ckeditor5-toolbar-button-sourceEditing') // Select the Source Editing button.
.keys(browser.Keys.DOWN) // Hit the down arrow key to move it to the toolbar.
// Wait for new source editing vertical tab to be present before continuing.
.waitForElementVisible(
'[href*=edit-editor-settings-plugins-ckeditor5-sourceediting]',
)
.submitForm('input[type="submit"]')
.waitForElementVisible('[data-drupal-messages]')
.assert.textContains('[data-drupal-messages]', 'Added text format')
// Create new content type.
.drupalRelativeURL('/admin/structure/types/add')
.waitForElementVisible('[data-drupal-selector="edit-name"]')
.updateValue('[data-drupal-selector="edit-name"]', 'test')
.waitForElementVisible('#edit-name-machine-name-suffix') // Wait for machine name to update.
.submitForm('input[type="submit"]')
.waitForElementVisible('[data-drupal-messages]')
.assert.textContains(
'[data-drupal-messages]',
'The content type test has been added',
)
// Navigate to the create content page and measure height of the editor.
.drupalRelativeURL('/node/add/test')
.waitForElementVisible('.ck-editor__editable')
.execute(
// eslint-disable-next-line func-names, prefer-arrow-callback, no-shadow
function () {
const height = document.querySelector(
'.ck-editor__editable',
).clientHeight;
// We expect height to be 320, but test to ensure that it's greater
// than 300. We want to ensure that we don't hard code a very specific
// value because tests might break if styles change (line-height, etc).
// Note that the default height for CKEditor5 is 47px.
return height > 300;
},
[],
(result) => {
browser.assert.ok(
result.value,
'Editor height is set to 9 rows (default).',
);
},
)
.click('.ck-source-editing-button')
.waitForElementVisible('.ck-source-editing-area')
.execute(
// eslint-disable-next-line func-names, prefer-arrow-callback, no-shadow
function () {
const height = document.querySelector(
'.ck-source-editing-area',
).clientHeight;
// We expect height to be 320, but test to ensure that it's greater
// than 300. We want to ensure that we don't hard code a very specific
// value because tests might break if styles change (line-height, etc).
// Note that the default height for CKEditor5 is 47px.
return height > 300;
},
[],
(result) => {
browser.assert.ok(
result.value,
'Source editing height is set to 9 rows (default).',
);
},
)
// Double the editor row count.
.drupalRelativeURL('/admin/structure/types/manage/test/form-display')
.waitForElementVisible(
'[data-drupal-selector="edit-fields-body-settings-edit"]',
)
.click('[data-drupal-selector="edit-fields-body-settings-edit"]')
.waitForElementVisible(
'[data-drupal-selector="edit-fields-body-settings-edit-form-settings-rows"]',
)
.updateValue(
'[data-drupal-selector="edit-fields-body-settings-edit-form-settings-rows"]',
'18',
)
// Save field settings.
.click(
'[data-drupal-selector="edit-fields-body-settings-edit-form-actions-save-settings"]',
)
.waitForElementVisible(
'[data-drupal-selector="edit-fields-body"] .field-plugin-summary',
)
.click('[data-drupal-selector="edit-submit"]')
.waitForElementVisible('[data-drupal-messages]')
.assert.textContains(
'[data-drupal-messages]',
'Your settings have been saved',
)
// Navigate to the create content page and measure height of the editor.
.drupalRelativeURL('/node/add/test')
.execute(
// eslint-disable-next-line func-names, prefer-arrow-callback, no-shadow
function () {
const height = document.querySelector(
'.ck-editor__editable',
).clientHeight;
// We expect height to be 640, but test to ensure that it's greater
// than 600. We want to ensure that we don't hard code a very specific
// value because tests might break if styles change (line-height, etc).
// Note that the default height for CKEditor5 is 47px.
return height > 600;
},
[],
(result) => {
browser.assert.ok(result.value, 'Editor height is set to 18 rows.');
},
)
.click('.ck-source-editing-button')
.waitForElementVisible('.ck-source-editing-area')
.execute(
// eslint-disable-next-line func-names, prefer-arrow-callback, no-shadow
function () {
const height = document.querySelector(
'.ck-source-editing-area',
).clientHeight;
// We expect height to be 640, but test to ensure that it's greater
// than 600. We want to ensure that we don't hard code a very specific
// value because tests might break if styles change (line-height, etc).
// Note that the default height for CKEditor5 is 47px.
return height > 600;
},
[],
(result) => {
browser.assert.ok(
result.value,
'Source editing height is set to 18 rows (default).',
);
},
);
});
},
};
...@@ -25,7 +25,7 @@ class TextareaWidget extends StringTextareaWidget { ...@@ -25,7 +25,7 @@ class TextareaWidget extends StringTextareaWidget {
*/ */
public function settingsForm(array $form, FormStateInterface $form_state) { public function settingsForm(array $form, FormStateInterface $form_state) {
$element = parent::settingsForm($form, $form_state); $element = parent::settingsForm($form, $form_state);
$element['rows']['#description'] = $this->t('Text editors (like CKEditor) may override this setting.'); $element['rows']['#description'] = $this->t('Text editors may override this setting.');
return $element; return $element;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment