diff --git a/addons/web_editor/static/src/js/editor/rte.js b/addons/web_editor/static/src/js/editor/rte.js index bfd7994b161..eecee43a5c6 100644 --- a/addons/web_editor/static/src/js/editor/rte.js +++ b/addons/web_editor/static/src/js/editor/rte.js @@ -323,11 +323,20 @@ var RTEWidget = Widget.extend({ }); // start element observation - $(document).on('content_changed', '.o_editable', function (ev) { + $(document).on('content_changed', function (ev) { self.trigger_up('rte_change', {target: ev.target}); + + // Add the dirty flag to the element that changed by either adding + // it on the highest editable ancestor or, if there is no editable + // ancestor, on the element itself (that element may not be editable + // but if it received a content_changed event, it should be marked + // as dirty to allow for custom savings). if (!ev.__isDirtyHandled) { - $(this).addClass('o_dirty'); ev.__isDirtyHandled = true; + + var el = ev.target; + var dirty = el.closest('.o_editable') || el; + dirty.classList.add('o_dirty'); } }); @@ -586,11 +595,16 @@ var RTEWidget = Widget.extend({ * page element) */ _saveElement: function ($el, context, withLang) { + var viewID = $el.data('oe-id'); + if (!viewID) { + return Promise.resolve(); + } + return this._rpc({ model: 'ir.ui.view', method: 'save', args: [ - $el.data('oe-id'), + viewID, this._getEscapedElement($el).prop('outerHTML'), $el.data('oe-xpath') || null, ], diff --git a/addons/web_editor/static/src/js/wysiwyg/wysiwyg_snippets.js b/addons/web_editor/static/src/js/wysiwyg/wysiwyg_snippets.js index 4b095029432..df6d243ffc6 100644 --- a/addons/web_editor/static/src/js/wysiwyg/wysiwyg_snippets.js +++ b/addons/web_editor/static/src/js/wysiwyg/wysiwyg_snippets.js @@ -20,8 +20,6 @@ Wysiwyg.include({ await this.editor.prependTo(this.$editor[0].ownerDocument.body); this.options.toolbarHandler.append(this.editor.$el); this.$el.on('content_changed', function (e) { - var $editable = $(e.target).closest('[data-oe-model], .o_editable'); - $editable.addClass('o_dirty'); self.trigger_up('wysiwyg_change'); }); } else { diff --git a/addons/website/static/src/js/editor/wysiwyg_multizone.js b/addons/website/static/src/js/editor/wysiwyg_multizone.js index 9ed31d3afe5..8c7fbfb2e0c 100644 --- a/addons/website/static/src/js/editor/wysiwyg_multizone.js +++ b/addons/website/static/src/js/editor/wysiwyg_multizone.js @@ -124,17 +124,23 @@ var WysiwygMultizone = Wysiwyg.extend({ */ _saveElement: function (outerHTML, recordInfo, editable) { var promises = []; + var $el = $(editable); - promises.push(this._rpc({ - model: 'ir.ui.view', - method: 'save', - args: [ - $el.data('oe-id'), - outerHTML, - $el.data('oe-xpath') || null, - ], - context: recordInfo.context, - })); + + var viewID = $el.data('oe-id'); + if (viewID) { + promises.push(this._rpc({ + model: 'ir.ui.view', + method: 'save', + args: [ + viewID, + outerHTML, + $el.data('oe-xpath') || null, + ], + context: recordInfo.context, + })); + } + if ($el.data('oe-field') === 'mega_menu_content') { // On top of saving the mega menu content like any other field // content, we must save the custom classes that were set on the @@ -153,6 +159,7 @@ var WysiwygMultizone = Wysiwyg.extend({ ], })); } + return Promise.all(promises); }, /** diff --git a/addons/website_blog/static/src/js/website_blog.editor.js b/addons/website_blog/static/src/js/website_blog.editor.js index de07e5440b2..6a262270557 100644 --- a/addons/website_blog/static/src/js/website_blog.editor.js +++ b/addons/website_blog/static/src/js/website_blog.editor.js @@ -90,31 +90,51 @@ WysiwygMultizone.include({ * @override */ _saveElement: function (outerHTML, recordInfo, editable) { - var defs = [this._super.apply(this, arguments)]; - // TODO the o_dirty class is not put on the right element for blog cover - // edition. For some strange reason, it was forcly put (even if not - // dirty) in <= saas-16 but this is not the case anymore. - var $blogContainer = $(editable).closest('.o_blog_cover_container'); - if (!this.__blogCoverSaved && $blogContainer.length) { - var $el = $blogContainer; - this.__blogCoverSaved = true; - defs.push(this._rpc({ - route: '/blog/post_change_background', - params: { - blog_id: parseInt($el.closest('[name="blog_post"], #o_wblog_blog_top, #o_wblog_post_top').find('[data-oe-model="blog.blog"]').first().data('oe-id'), 10), - post_id: parseInt($el.closest('[name="blog_post"], #o_wblog_blog_top, #o_wblog_post_top').find('[data-oe-model="blog.post"]').first().data('oe-id'), 10), - cover_properties: { - 'background-image': $el.find('.o_blog_cover_image').css('background-image').replace(/"/g, '').replace(window.location.protocol + "//" + window.location.host, ''), - 'background-color': $el.attr('data-filter-color'), - 'opacity': $el.attr('data-filter-value'), - 'resize_class': $el.attr('data-cover-class'), - 'text_size_class': $el.attr('data-text-size-class'), - 'text_align_class': $el.attr('data-text-align-class'), - }, - }, - })); + var prom = this._super.apply(this, arguments); + + var el = editable.closest('.o_blog_cover_container'); + if (!el) { + return prom; } - return Promise.all(defs); + + var ancestor = el.closest('[name="blog_post"], #o_wblog_blog_top, #o_wblog_post_top'); + var blogID = parseInt($(ancestor.querySelector('[data-oe-model="blog.blog"]')).data('oe-id'), 10); + var postID = parseInt($(ancestor.querySelector('[data-oe-model="blog.post"]')).data('oe-id'), 10); + + if (blogID) { + this.__savedCoversBlogIDs = this.__savedCoversBlogIDs || []; + if (this.__savedCoversBlogIDs.includes(blogID)) { + return prom; + } + this.__savedCoversBlogIDs.push(blogID); + } + if (postID) { + this.__savedCoversPostIDs = this.__savedCoversPostIDs || []; + if (this.__savedCoversPostIDs.includes(postID)) { + return prom; + } + this.__savedCoversPostIDs.push(postID); + } + + var cssBgImage = $(el.querySelector('.o_blog_cover_image')).css('background-image'); + + var prom2 = this._rpc({ + route: '/blog/post_change_background', + params: { + 'blog_id': blogID, + 'post_id': postID, + 'cover_properties': { + 'background-image': cssBgImage.replace(/"/g, '').replace(window.location.protocol + "//" + window.location.host, ''), + 'background-color': el.dataset.filterColor, + 'opacity': el.dataset.filterValue, + 'resize_class': el.dataset.coverClass, + 'text_size_class': el.dataset.textSizeClass, + 'text_align_class': el.dataset.textAlignClass, + }, + }, + }); + + return Promise.all([prom, prom2]); }, }); @@ -270,11 +290,11 @@ options.registry.blog_cover = options.Class.extend({ return self.$filter.hasClass($(this).data('filterColor')); }).addClass('active').data('filterColor'); - this.$target.attr('data-cover-class', this.$el.find('.active[data-cover-opt="size"]').data('selectClass') || ''); - this.$target.attr('data-text-size-class', this.$el.find('.active[data-cover-opt="text_size"]').data('selectClass') || ''); - this.$target.attr('data-text-align-class', this.$el.find('.active[data-cover-opt="text_align"]').data('selectClass') || ''); - this.$target.attr('data-filter-value', activeFilterValue || 0.0); - this.$target.attr('data-filter-color', activeFilterColor || ''); + this.$target[0].dataset.coverClass = this.$el.find('.active[data-cover-opt="size"]').data('selectClass') || ''; + this.$target[0].dataset.textSizeClass = this.$el.find('.active[data-cover-opt="text_size"]').data('selectClass') || ''; + this.$target[0].dataset.textAlignClass = this.$el.find('.active[data-cover-opt="text_align"]').data('selectClass') || ''; + this.$target[0].dataset.filterValue = activeFilterValue || 0.0; + this.$target[0].dataset.filterColor = activeFilterColor || ''; }, }); });