Skip to content

Commit d3de4ad

Browse files
authored
HtmlEditor: header format should be reset on move to next line by enter press (T1315504) (#32012)
1 parent a59c76c commit d3de4ad

File tree

2 files changed

+111
-1
lines changed

2 files changed

+111
-1
lines changed

packages/devextreme/js/__internal/ui/html_editor/modules/m_toolbar.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,13 +134,16 @@ if (Quill) {
134134
}
135135

136136
this.quill.on('editor-change', (eventName, newValue, oldValue, eventSource) => {
137-
const isSilentMode = eventSource === SILENT_ACTION && isEmptyObject(this.quill.getFormat());
137+
const isSilentMode = eventSource === SILENT_ACTION
138+
&& isEmptyObject(this.quill.getFormat());
138139

139140
if (!isSilentMode) {
140141
const isSelectionChanged = eventName === SELECTION_CHANGE_EVENT;
141142

142143
this._updateToolbar(isSelectionChanged);
143144
}
145+
146+
this._updateHeaderFormatWidget();
144147
});
145148
}
146149
}
@@ -671,6 +674,18 @@ if (Quill) {
671674
this._toggleClearFormatting(hasFormats || selection.length > 1);
672675
}
673676

677+
_updateHeaderFormatWidget() {
678+
const selection = this.quill.getSelection();
679+
const formatName = 'header';
680+
const formatWidget = this._toolbarWidgets.getByName(formatName);
681+
const formats = this.quill.getFormat(selection);
682+
if (!selection || !formatWidget) {
683+
return;
684+
}
685+
686+
this._markActiveFormatWidget(formatName, formatWidget, formats);
687+
}
688+
674689
_markActiveFormatWidget(name, widget, formats) {
675690
if (this._isColorFormat(name)) {
676691
this._updateColorWidget(name, formats[name]);

packages/devextreme/testing/tests/DevExpress.ui.widgets.htmlEditor/htmlEditorParts/toolbarIntegration.tests.js

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,21 @@ import $ from 'jquery';
33
import 'ui/html_editor';
44
import fx from 'common/core/animation/fx';
55

6+
import nativePointerMock from '../../../helpers/nativePointerMock.js';
67
import { checkLink, prepareEmbedValue, prepareTableValue } from './utils.js';
78

89
const TOOLBAR_CLASS = 'dx-htmleditor-toolbar';
910
const TOOLBAR_WRAPPER_CLASS = 'dx-htmleditor-toolbar-wrapper';
1011
const TOOLBAR_FORMAT_WIDGET_CLASS = 'dx-htmleditor-toolbar-format';
1112
const TOOLBAR_MULTILINE_CLASS = 'dx-toolbar-multiline';
1213
const TOOLBAR_FORMAT_BUTTON_ACTIVE_CLASS = 'dx-format-active';
14+
const HTML_EDITOR_CONTENT_CLASS = 'dx-htmleditor-content';
1315
const DROPDOWNMENU_CLASS = 'dx-dropdownmenu-button';
1416
const DROPDOWNEDITOR_ICON_CLASS = 'dx-dropdowneditor-icon';
1517
const BUTTON_CONTENT_CLASS = 'dx-button-content';
1618
const QUILL_CONTAINER_CLASS = 'dx-quill-container';
1719
const STATE_DISABLED_CLASS = 'dx-state-disabled';
20+
const FORMAT_ACTIVE_CLASS = 'dx-format-active';
1821
const HEX_FIELD_CLASS = 'dx-colorview-label-hex';
1922
const INPUT_CLASS = 'dx-texteditor-input';
2023
const DIALOG_CLASS = 'dx-formdialog';
@@ -25,6 +28,8 @@ const LIST_ITEM_CLASS = 'dx-list-item';
2528

2629
const BLACK_PIXEL = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQYGWNgYmL6DwABFgEGpP/tHAAAAABJRU5ErkJggg==';
2730

31+
const ENTER_KEY_CODE = 13;
32+
2833
const { test, module: testModule } = QUnit;
2934

3035
function getToolbar($container) {
@@ -146,6 +151,96 @@ export default function() {
146151
.trigger('dxclick');
147152
});
148153

154+
test('header format should be reset after moving to next line (T1315504)', function(assert) {
155+
const $htmlEditor = $('#htmlEditor').dxHtmlEditor({
156+
value: '<p>test</p>',
157+
toolbar: {
158+
items: [{
159+
name: 'header',
160+
acceptedValues: [false, 1, 2, 3, 4, 5],
161+
options: {
162+
opened: true
163+
},
164+
}],
165+
multiline: false
166+
},
167+
});
168+
const htmlEditor = $htmlEditor.dxHtmlEditor('instance');
169+
const $formatWidget = $htmlEditor.find(`.${TOOLBAR_FORMAT_WIDGET_CLASS}`);
170+
const $content = $htmlEditor.find(`.${HTML_EDITOR_CONTENT_CLASS}`);
171+
htmlEditor.setSelection(4, 0);
172+
173+
$(`.${LIST_ITEM_CLASS}`)
174+
.last()
175+
.trigger('dxclick');
176+
177+
178+
const value = $formatWidget.find(`.${INPUT_CLASS}`).val();
179+
assert.strictEqual(value, 'Heading 5', 'Header format is applied');
180+
181+
nativePointerMock().simulateEvent($content.get(0), 'keydown', { keyCode: ENTER_KEY_CODE });
182+
183+
const newValue = $formatWidget.find(`.${INPUT_CLASS}`).val();
184+
assert.strictEqual(newValue, 'Normal text', 'Header format is reset');
185+
});
186+
187+
test('font format should not be reset after moving to next line', function(assert) {
188+
const $htmlEditor = $('#htmlEditor').dxHtmlEditor({
189+
value: '<p>test</p>',
190+
toolbar: {
191+
items: [{
192+
name: 'font',
193+
acceptedValues: ['Arial', 'Courier New', 'Georgia'],
194+
options: {
195+
opened: true
196+
},
197+
}],
198+
multiline: false
199+
},
200+
});
201+
const htmlEditor = $htmlEditor.dxHtmlEditor('instance');
202+
const $formatWidget = $htmlEditor.find(`.${TOOLBAR_FORMAT_WIDGET_CLASS}`);
203+
const $content = $htmlEditor.find(`.${HTML_EDITOR_CONTENT_CLASS}`);
204+
htmlEditor.setSelection(4, 0);
205+
206+
$(`.${LIST_ITEM_CLASS}`)
207+
.last()
208+
.trigger('dxclick');
209+
210+
211+
const value = $formatWidget.find(`.${INPUT_CLASS}`).val();
212+
assert.strictEqual(value, 'Georgia', 'Font format is applied');
213+
214+
nativePointerMock().simulateEvent($content.get(0), 'keydown', { keyCode: ENTER_KEY_CODE });
215+
216+
const newValue = $formatWidget.find(`.${INPUT_CLASS}`).val();
217+
assert.strictEqual(newValue, 'Georgia', 'Font format is not reset');
218+
});
219+
220+
['bold', 'italic', 'strike', 'underline'].forEach((formatName) => {
221+
test(`${formatName} format should not be reset after moving to next line`, function(assert) {
222+
const $htmlEditor = $('#htmlEditor').dxHtmlEditor({
223+
value: '<p>test</p>',
224+
toolbar: {
225+
items: [formatName],
226+
multiline: false
227+
},
228+
});
229+
const htmlEditor = $htmlEditor.dxHtmlEditor('instance');
230+
const $formatWidget = $htmlEditor.find(`.${TOOLBAR_FORMAT_WIDGET_CLASS}`);
231+
const $content = $htmlEditor.find(`.${HTML_EDITOR_CONTENT_CLASS}`);
232+
htmlEditor.setSelection(4, 0);
233+
234+
$formatWidget.trigger('dxclick');
235+
236+
assert.strictEqual($formatWidget.hasClass(FORMAT_ACTIVE_CLASS), true, `${formatName} format is applied`);
237+
238+
nativePointerMock().simulateEvent($content.get(0), 'keydown', { keyCode: ENTER_KEY_CODE });
239+
240+
assert.strictEqual($formatWidget.hasClass(FORMAT_ACTIVE_CLASS), true, `${formatName} format is not reset`);
241+
});
242+
});
243+
149244
test('adaptive menu should be hidden after selecting formatting', function(assert) {
150245
const done = assert.async();
151246
const instance = $('#htmlEditor').dxHtmlEditor({

0 commit comments

Comments
 (0)