Skip to content

Commit 570af50

Browse files
committed
WYSIWYG: Added justify cell range cleanup
To help override & gain control of setting text alignment in tables. - Adds support of clearing "align" attributes in certain operations. - Updates cell range action handling to dedupe execcommand handling. - Adds clearing of additional alignment classes on direction control. Closes #5011
1 parent 3891328 commit 570af50

File tree

1 file changed

+64
-27
lines changed

1 file changed

+64
-27
lines changed

resources/js/wysiwyg/fixes.js

Lines changed: 64 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -55,23 +55,43 @@ export function handleEmbedAlignmentChanges(editor) {
5555
});
5656
}
5757

58+
/**
59+
* Cleans up and removes text-alignment specific properties on all child elements.
60+
* @param {HTMLElement} element
61+
*/
62+
function cleanChildAlignment(element) {
63+
const alignedChildren = element.querySelectorAll('[align],[style*="text-align"],.align-center,.align-left,.align-right');
64+
for (const child of alignedChildren) {
65+
child.removeAttribute('align');
66+
child.style.textAlign = null;
67+
child.classList.remove('align-center', 'align-right', 'align-left');
68+
}
69+
}
70+
5871
/**
5972
* Cleans up the direction property for an element.
6073
* Removes all inline direction control from child elements.
6174
* Removes non "dir" attribute direction control from provided element.
6275
* @param {HTMLElement} element
6376
*/
6477
function cleanElementDirection(element) {
65-
const directionChildren = element.querySelectorAll('[dir],[style*="direction"],[style*="text-align"]');
78+
const directionChildren = element.querySelectorAll('[dir],[style*="direction"]');
6679
for (const child of directionChildren) {
6780
child.removeAttribute('dir');
6881
child.style.direction = null;
69-
child.style.textAlign = null;
7082
}
83+
84+
cleanChildAlignment(element);
7185
element.style.direction = null;
7286
element.style.textAlign = null;
87+
element.removeAttribute('align');
7388
}
7489

90+
/**
91+
* @typedef {Function} TableCellHandler
92+
* @param {HTMLTableCellElement} cell
93+
*/
94+
7595
/**
7696
* This tracks table cell range selection, so we can apply custom handling where
7797
* required to actions applied to such selections.
@@ -90,34 +110,51 @@ export function handleTableCellRangeEvents(editor) {
90110
selectedCells = [];
91111
});
92112

93-
// TinyMCE does not seem to do a great job on clearing styles in complex
94-
// scenarios (like copied word content) when a range of table cells
95-
// are selected. Here we watch for clear formatting events, so some manual
96-
// cleanup can be performed.
97-
const attrsToRemove = ['class', 'style', 'width', 'height'];
98-
editor.on('ExecCommand', event => {
99-
if (event.command === 'RemoveFormat') {
100-
for (const cell of selectedCells) {
101-
for (const attr of attrsToRemove) {
102-
cell.removeAttribute(attr);
103-
}
113+
/**
114+
* @type {Object<String, TableCellHandler>}
115+
*/
116+
const actionByCommand = {
117+
// TinyMCE does not seem to do a great job on clearing styles in complex
118+
// scenarios (like copied word content) when a range of table cells
119+
// are selected. Here we watch for clear formatting events, so some manual
120+
// cleanup can be performed.
121+
RemoveFormat: cell => {
122+
const attrsToRemove = ['class', 'style', 'width', 'height', 'align'];
123+
for (const attr of attrsToRemove) {
124+
cell.removeAttribute(attr);
104125
}
105-
}
106-
});
107-
108-
// TinyMCE does not apply direction events to table cell range selections
109-
// so here we hastily patch in that ability by setting the direction ourselves
110-
// when a direction event is fired.
111-
editor.on('ExecCommand', event => {
112-
const command = event.command;
113-
if (command !== 'mceDirectionLTR' && command !== 'mceDirectionRTL') {
114-
return;
115-
}
126+
},
116127

117-
const dir = command === 'mceDirectionLTR' ? 'ltr' : 'rtl';
118-
for (const cell of selectedCells) {
119-
cell.setAttribute('dir', dir);
128+
// TinyMCE does not apply direction events to table cell range selections
129+
// so here we hastily patch in that ability by setting the direction ourselves
130+
// when a direction event is fired.
131+
mceDirectionLTR: cell => {
132+
cell.setAttribute('dir', 'ltr');
133+
cleanElementDirection(cell);
134+
},
135+
mceDirectionRTL: cell => {
136+
cell.setAttribute('dir', 'rtl');
120137
cleanElementDirection(cell);
138+
},
139+
140+
// The "align" attribute can exist on table elements so this clears
141+
// the attribute, and also clears common child alignment properties,
142+
// when a text direction action is made for a table cell range.
143+
JustifyLeft: cell => {
144+
cell.removeAttribute('align');
145+
cleanChildAlignment(cell);
146+
},
147+
JustifyRight: this.JustifyLeft,
148+
JustifyCenter: this.JustifyLeft,
149+
JustifyFull: this.JustifyLeft,
150+
};
151+
152+
editor.on('ExecCommand', event => {
153+
const action = actionByCommand[event.command];
154+
if (action) {
155+
for (const cell of selectedCells) {
156+
action(cell);
157+
}
121158
}
122159
});
123160
}

0 commit comments

Comments
 (0)