[FIX] web_editor, web: fix traceback with drag & drop when no header

Commit [1] introduced the bug by relying on the fact an element with
id=top is in the edited DOM. As the website header can be disabled, this
induced a crash as soon as the header was indeed disabled. Also, the
editor is not meant to edit the website only so we cannot rely at all
on the presence of a #top element.

[1]: https://github.com/odoo/odoo/commit/6df67a28c2f113572acd4a3db19ab6b1bd37e7da

closes odoo/odoo#54409

Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
This commit is contained in:
qsm-odoo
2020-07-13 15:24:07 +00:00
parent b558cb7996
commit b9ad60d5eb
3 changed files with 42 additions and 24 deletions
@@ -21,25 +21,25 @@ const OffsetElementsHelper = Class.extend({
this.offsetElements = offsetElements;
},
top: function () {
if (!this.offsetElements.$top) {
if (!this.offsetElements.$top || !this.offsetElements.$top.length) {
return 0;
}
return this.offsetElements.$top.get(0).getBoundingClientRect().bottom;
},
right: function () {
if (!this.offsetElements.$right) {
if (!this.offsetElements.$right || !this.offsetElements.$right.length) {
return 0;
}
return this.offsetElements.$right.get(0).getBoundingClientRect().left;
},
bottom: function () {
if (!this.offsetElements.$bottom) {
if (!this.offsetElements.$bottom || !this.offsetElements.$bottom.length) {
return 0;
}
return this.offsetElements.$bottom.get(0).getBoundingClientRect().top;
},
left: function () {
if (!this.offsetElements.$left) {
if (!this.offsetElements.$left || !this.offsetElements.$left.length) {
return 0;
}
return this.offsetElements.$left.get(0).getBoundingClientRect().right;
@@ -72,26 +72,18 @@ var SnippetEditor = Widget.extend({
// Initialize move/clone/remove buttons
if (this.isTargetMovable) {
this.dropped = false;
const smoothScrollOptions = {
offsetElements: {
$top: $('#top'),
$left: $('#oe_snippets'),
},
const smoothScrollOptions = this.options.getScrollOptions({
jQueryDraggableOptions: {
appendTo: this.$body,
cursor: 'move',
cursorAt: {
left: 10,
top: 10
},
greedy: true,
handle: '.o_move_handle',
helper: () => {
var $clone = this.$el.clone().css({width: '24px', height: '24px', border: 0});
$clone.appendTo(this.$body).removeClass('d-none');
return $clone;
},
scroll: false,
start: this._onDragAndDropStart.bind(this),
stop: (...args) => {
// Delay our stop handler so that some summernote handlers
@@ -103,7 +95,7 @@ var SnippetEditor = Widget.extend({
}, 0);
},
},
};
});
this.draggableComponent = new SmoothScrollOnDrag(this, this.$el, $('html'), smoothScrollOptions);
} else {
this.$('.o_overlay_move_options').addClass('d-none');
@@ -932,6 +924,8 @@ var SnippetsMenu = Widget.extend({
this._addTabLoading(this.tabs.BLOCKS);
this.options.getScrollOptions = this._getScrollOptions.bind(this);
// Fetch snippet templates and compute it
defs.push(this._loadSnippetsTemplates().then(() => {
return this._updateInvisibleDOM();
@@ -1736,6 +1730,25 @@ var SnippetsMenu = Widget.extend({
$snippet.toggleClass('o_disabled', !check);
});
},
/**
* @private
* @param {Object} [options={}]
* @returns {Object}
*/
_getScrollOptions(options = {}) {
return Object.assign({}, options, {
offsetElements: Object.assign({
$top: $('#web_editor-top-edit'), // TODO should ideally be retrieved another way
$left: this.$el,
}, options.offsetElements),
jQueryDraggableOptions: Object.assign({
appendTo: this.$body,
cursor: 'move',
greedy: true,
scroll: false,
}, options.jQueryDraggableOptions),
});
},
/**
* Creates a dropzone element and inserts it by replacing the given jQuery
* location. This allows to add data on the dropzone depending on the hook
@@ -1766,16 +1779,9 @@ var SnippetsMenu = Widget.extend({
var self = this;
var $toInsert, dropped, $snippet;
const smoothScrollOptions = {
offsetElements: {
$top: $('#top'),
$left: $('#oe_snippets'),
},
const smoothScrollOptions = this._getScrollOptions({
jQueryDraggableOptions: {
appendTo: this.$body,
cursor: 'move',
distance: 0,
greedy: true,
handle: '.oe_snippet_thumbnail',
helper: function () {
const dragSnip = this.cloneNode(true);
@@ -1784,7 +1790,6 @@ var SnippetsMenu = Widget.extend({
);
return dragSnip;
},
scroll: false,
start: function () {
dropped = false;
$snippet = $(this);
@@ -1882,7 +1887,7 @@ var SnippetsMenu = Widget.extend({
}
},
},
};
});
this.draggableComponent = new SmoothScrollOnDrag(this, $snippets, $('html'), smoothScrollOptions);
},
/**
@@ -30,6 +30,19 @@ weSnippetEditor.Class.include({
return this._super(...arguments);
},
/**
* @override
*/
_getScrollOptions(options = {}) {
const finalOptions = this._super(...arguments);
if (!options.offsetElements || !options.offsetElements.$top) {
const $header = $('#top');
if ($header.length) {
finalOptions.offsetElements.$top = $header;
}
}
return finalOptions;
},
/**
* @override
*/