From 3bb892cfab38fbf91a6bb04e9e70abe7ca4711aa Mon Sep 17 00:00:00 2001 From: Samuel Degueldre Date: Wed, 28 Oct 2020 13:56:52 +0000 Subject: [PATCH] [FIX] web_editor: fix icons losing classes when modifying them Previously, when double clicking and image, video, icon, or document in the web-editor and replacing it with a different media type, it would lose its custom classes. This means among other things, that it would lose margins and paddings from bootstrap classes, or in the case of the three columns snippet, that the new media would not be properly rounded in its top corner, or not show up at all in the case of the video. The only exception was when changing any media type to an icon, but in that case it would also keep some of the media-specific classes that are supposed to be removed (eg img-fluid or media_iframe_video). This commit fixes that as well as some _clear behaviour that didn't remove all classes that had to be removed, eg some fa-classes would linger depending on their order, and the o_image class from documents would always remain Part of https://github.com/odoo/odoo/pull/64234 task-2282542 closes odoo/odoo#64234 X-original-commit: 99531f5dd8966fc4ad89d1e9c2886ad701527f3a Signed-off-by: Quentin Smetz (qsm) --- addons/web/static/src/scss/mimetypes.scss | 2 ++ .../static/src/js/wysiwyg/widgets/media.js | 29 +++++++++---------- .../src/js/wysiwyg/widgets/media_dialog.js | 13 ++++++++- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/addons/web/static/src/scss/mimetypes.scss b/addons/web/static/src/scss/mimetypes.scss index f366f7eed97..678116e12ab 100644 --- a/addons/web/static/src/scss/mimetypes.scss +++ b/addons/web/static/src/scss/mimetypes.scss @@ -4,6 +4,8 @@ height: 38px; background-image: url('/web/static/src/img/mimetypes/unknown.svg'); background-size: contain; + background-repeat: no-repeat; + background-position: center; &[data-mimetype^='image'] { background-image: url('/web/static/src/img/mimetypes/image.svg'); diff --git a/addons/web_editor/static/src/js/wysiwyg/widgets/media.js b/addons/web_editor/static/src/js/wysiwyg/widgets/media.js index 80e8bd998fb..27397e9c8a2 100644 --- a/addons/web_editor/static/src/js/wysiwyg/widgets/media.js +++ b/addons/web_editor/static/src/js/wysiwyg/widgets/media.js @@ -251,15 +251,7 @@ var FileWidget = SearchableMediaWidget.extend({ * @override */ _clear: function () { - if (this.$media.is('img')) { - return; - } - var allImgClasses = /(^|\s+)((img(\s|$)|img-(?!circle|rounded|thumbnail))[^\s]*)/g; - var allImgClassModifiers = /(^|\s+)(rounded-circle|shadow|rounded|img-thumbnail|mx-auto)([^\s]*)/g; - this.media.className = this.media.className && this.media.className - .replace('o_we_custom_image', '') - .replace(allImgClasses, ' ') - .replace(allImgClassModifiers, ' '); + this.media.className = this.media.className && this.media.className.replace(/(^|\s+)(o_image)(?=\s|$)/g, ' '); }, /** * Returns the domain for attachments used in media dialog. @@ -977,6 +969,14 @@ var ImageWidget = FileWidget.extend({ this.libraryMedia = []; this._super(...arguments); }, + /** + * @override + */ + _clear: function (type) { + // Not calling _super: we don't want to call the document widget's _clear method on images + var allImgClasses = /(^|\s+)(img|img-\S*|o_we_custom_image|rounded-circle|rounded|thumbnail|shadow)(?=\s|$)/g; + this.media.className = this.media.className && this.media.className.replace(allImgClasses, ' '); + }, }); @@ -1056,10 +1056,10 @@ var IconWidget = SearchableMediaWidget.extend({ var cls = classes[i]; if (_.contains(this.alias, cls)) { this.selectedIcon = cls; + this.initialIcon = cls; this._highlightSelectedIcon(); } } - this.nonIconClasses = _.without(classes, 'media_iframe_video', this.selectedIcon); return this._super.apply(this, arguments); }, @@ -1074,7 +1074,6 @@ var IconWidget = SearchableMediaWidget.extend({ save: function () { var style = this.$media.attr('style') || ''; var iconFont = this._getFont(this.selectedIcon) || {base: 'fa', font: ''}; - var finalClasses = _.uniq(this.nonIconClasses.concat([iconFont.base, iconFont.font])); if (!this.$media.is('span, i')) { var $span = $(''); $span.data(this.$media.data()); @@ -1082,10 +1081,8 @@ var IconWidget = SearchableMediaWidget.extend({ this.media = this.$media[0]; style = style.replace(/\s*width:[^;]+/, ''); } - this.$media.attr({ - class: _.compact(finalClasses).join(' '), - style: style || null, - }); + this.$media.removeClass(this.initialIcon).addClass([iconFont.base, iconFont.font]); + this.$media.attr('style', style || null); return Promise.resolve(this.media); }, /** @@ -1123,7 +1120,7 @@ var IconWidget = SearchableMediaWidget.extend({ * @override */ _clear: function () { - var allFaClasses = /(^|\s)(fa(\s|$)|fa-[^\s]*)/g; + var allFaClasses = /(^|\s)(fa|(text-|bg-|fa-)\S*|rounded-circle|rounded|thumbnail|shadow)(?=\s|$)/g; this.media.className = this.media.className && this.media.className.replace(allFaClasses, ' '); }, /** diff --git a/addons/web_editor/static/src/js/wysiwyg/widgets/media_dialog.js b/addons/web_editor/static/src/js/wysiwyg/widgets/media_dialog.js index 51e38e86c83..6c4c568dc5a 100644 --- a/addons/web_editor/static/src/js/wysiwyg/widgets/media_dialog.js +++ b/addons/web_editor/static/src/js/wysiwyg/widgets/media_dialog.js @@ -39,6 +39,7 @@ var MediaDialog = Dialog.extend({ init: function (parent, options, media) { var $media = $(media); media = $media[0]; + this.media = media; options = _.extend({}, options); var onlyImages = options.onlyImages || this.multiImages || (media && ($media.parent().data('oeField') === 'image' || $media.parent().data('oeType') === 'image')); @@ -75,6 +76,7 @@ var MediaDialog = Dialog.extend({ } else { this.activeWidget = [this.imageWidget, this.documentWidget, this.videoWidget, this.iconWidget].find(w => !!w); } + this.initiallyActiveWidget = this.activeWidget; }, /** * Adds the appropriate class to the current modal and appends the media @@ -153,7 +155,16 @@ var MediaDialog = Dialog.extend({ var _super = this._super; var args = arguments; return this.activeWidget.save().then(function (data) { - self._clearWidgets(); + if (self.activeWidget !== self.initiallyActiveWidget) { + self._clearWidgets(); + } + // Restore classes if the media was replaced (when changing type) + if (self.media !== data) { + var oldClasses = self.media && _.toArray(self.media.classList); + if (oldClasses) { + data.className = _.union(_.toArray(data.classList), oldClasses).join(' '); + } + } self.final_data = data; _super.apply(self, args); $(data).trigger('content_changed');