[FIX] web_editor: browser-unify alignment editor option
Summernote uses `document.execCommand` to apply most styles when editing, leveraging the implementation to the browser. Summernote is configured to use HTML styling (`'styleWithSpan': false`), and in this case, browsers such as Firefox use HTML attributes for styling text align, while Chrome still uses CSS for that. In fact, `document.execCommand` is browser-inconsistent... but so is the `styleWithSpan` option. Indeed, setting the option to `true` will make Firefox use CSS property for alignment too... but not Internet Explorer. So we might consider changing this option's value but this would not solve the current problem. Indeed, any CSS `text-align` style in Firefox takes precedence above the element's `align` attribute, so when users were trying to align text on stuff that was pre-aligned, they were unable to do so. We can better explain the situation with this example: A user tries to left-align in Firefox a `p.text-center` element, and produces this: ```html <p class="text-center" align="left"/> ``` (`align` attribute is ignored because of the `text-center` class) On Chrome, this would be produced with the same steps: ```html <p class="text-center" style="text-align:left"/> ``` With this patch, we actually make that HTML look like expected by the user, no matter the browser he's using, by forcing the editor to use the text-align CSS property. Note that the implementation is quite ugly but had to take care of compatibility. See https://github.com/odoo/odoo/pull/20900 (thanks to @Yajo for original PR)
This commit is contained in:
@@ -19,6 +19,57 @@ var editor = eventHandler.modules.editor;
|
||||
var renderer = $.summernote.renderer;
|
||||
var options = $.summernote.options;
|
||||
|
||||
// Browser-unify execCommand
|
||||
var oldJustify = {};
|
||||
_.each(['Left', 'Right', 'Full', 'Center'], function (align) {
|
||||
oldJustify[align] = editor['justify' + align];
|
||||
editor['justify' + align] = function ($editable, value) {
|
||||
// Before calling the standard function, check all elements which have
|
||||
// an 'align' attribute and mark them with their value
|
||||
var $align = $editable.find('[align]');
|
||||
_.each($align, function (el) {
|
||||
var $el = $(el);
|
||||
$el.data('__align', $el.attr('align'));
|
||||
});
|
||||
|
||||
// Call the standard function
|
||||
oldJustify[align].apply(this, arguments);
|
||||
|
||||
// Then:
|
||||
|
||||
// Remove the text-align of elements which lost the 'align' attribute
|
||||
var $newAlign = $editable.find('[align]');
|
||||
$align.not($newAlign).css('text-align', '');
|
||||
|
||||
// Transform the 'align' attribute into the 'text-align' css
|
||||
// property for elements which received the 'align' attribute or whose
|
||||
// 'align' attribute changed
|
||||
_.each($newAlign, function (el) {
|
||||
var $el = $(el);
|
||||
|
||||
var oldAlignValue = $align.data('__align');
|
||||
var alignValue = $el.attr('align');
|
||||
if (oldAlignValue === alignValue) {
|
||||
// If the element already had an 'align' attribute and that it
|
||||
// did not changed, do nothing (compatibility)
|
||||
return;
|
||||
}
|
||||
|
||||
$el.removeAttr('align');
|
||||
$el.css('text-align', alignValue);
|
||||
|
||||
// Note the first step (removing the text-align of elemnts which
|
||||
// lost the 'align' attribute) is kinda the same as this one, but
|
||||
// this one handles the elements which have been edited with chrome
|
||||
// or with this new system
|
||||
$el.find('*').css('text-align', '');
|
||||
});
|
||||
|
||||
// Unmark the elements
|
||||
$align.removeData('__align');
|
||||
};
|
||||
});
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Add method to Summernote*/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user