[FIX] web_editor: table colored borders scrolling with viewport

Before this commit:

The table menu is appended directly to the body, causing issues when scrolling.
This results in the table menu toggler scrolling through the navbar, and the
position of the table menu toggler does not update on during scrolling.

After this commit:

The table UI and the editor are siblings, it eliminate's any z-index
issues. Additionally, the position of the table menu toggler is updated during
scroll.

task-3429097

closes odoo/odoo#144863

X-original-commit: f88d190a0de6328cd8dc8872be07c51f76935c3a
Signed-off-by: Antoine Guenet (age) <age@odoo.com>
This commit is contained in:
visp-odoo
2023-12-05 21:15:19 +00:00
parent 4dc2e99772
commit dd5f01d5d2
2 changed files with 28 additions and 17 deletions
@@ -405,6 +405,8 @@ export class OdooEditor extends EventTarget {
});
});
// Create the table UI.
this._tableUiContainer = this.document.createElement('div');
this._tableUiContainer.classList.add('o_table_ui_container');
const parser = new DOMParser();
for (const direction of ['row', 'column']) {
// Create the containers and the menu toggler.
@@ -468,8 +470,9 @@ export class OdooEditor extends EventTarget {
this.addDomListener(uiMenu.querySelector('.o_reset_table_size'), 'click', () => this.execCommand('resetSize', this._tableUiTarget));
this[`_${direction}Ui`] = ui;
this.document.body.append(ui);
this._tableUiContainer.append(ui);
this.addDomListener(ui.querySelector('.o_table_ui_menu_toggler'), 'click', this._onTableMenuTogglerClick);
this.editable.before(this._tableUiContainer);
}
// --------
@@ -674,6 +677,7 @@ export class OdooEditor extends EventTarget {
this.addDomListener(this.document, 'keyup', this._onDocumentKeyup);
this.addDomListener(this.document, 'mouseup', this._onDocumentMouseup);
this.addDomListener(this.document, 'click', this._onDocumentClick);
this.addDomListener(this.document, 'scroll', this._onScroll, true);
this.multiselectionRefresh = this.multiselectionRefresh.bind(this);
this._resizeObserver = new ResizeObserver(this.multiselectionRefresh);
@@ -907,10 +911,10 @@ export class OdooEditor extends EventTarget {
this.options.onPostSanitize(target);
}
addDomListener(element, eventName, callback) {
addDomListener(element, eventName, callback, useCapture) {
const boundCallback = callback.bind(this);
this._domListeners.push([element, eventName, boundCallback]);
element.addEventListener(eventName, boundCallback);
element.addEventListener(eventName, boundCallback, useCapture);
}
/**
@@ -2905,16 +2909,11 @@ export class OdooEditor extends EventTarget {
* @param {HTMLTableRowElement|HTMLTableCellElement} element
*/
_positionTableUi(element) {
const tableUiContainerRect = this._tableUiContainer.getBoundingClientRect();
const isRow = element.nodeName === 'TR';
const ui = isRow ? this._rowUi : this._columnUi;
const elementRect = element.getBoundingClientRect();
const tableRect = closestElement(element, 'table').getBoundingClientRect();
const wrappedUi = ui.firstElementChild;
const togglerRect = ui.querySelector('.o_table_ui_menu_toggler').getBoundingClientRect();
const props = {
xy: {left: 'x', top: 'y'},
size: {left: 'width', top: 'height'}
};
const table = getInSelection(this.document, 'table');
const resetTableSize = ui.querySelector('.o_reset_table_size');
if (table && !table.hasAttribute('style')) {
@@ -2922,15 +2921,10 @@ export class OdooEditor extends EventTarget {
} else {
resetTableSize.classList.remove('d-none');
}
const side1 = isRow ? 'left' : 'top';
ui.style[side1] = (isRow ? elementRect : tableRect)[props.xy[side1]] - togglerRect[props.size[side1]] + 'px';
ui.style[props.size[side1]] = !isRow && togglerRect[props.size[side1]] + 'px';
ui.style.left = elementRect.left - tableUiContainerRect.left - (isRow ? wrappedUi.clientWidth : 0) + 'px';
ui.style.top = elementRect.top - tableUiContainerRect.top - (isRow ? 0 : wrappedUi.clientHeight) + 'px';
wrappedUi.style[isRow ? 'height' : 'width'] = elementRect[isRow ? 'height' : 'width'] + 'px';
const side2 = isRow ? 'top' : 'left';
wrappedUi.style[props.size[side2]] = elementRect[props.size[side2]] + 'px';
ui.style[side2] = tableRect[props.xy[side2]] + 'px';
wrappedUi.style[side2] = elementRect[side2] - tableRect[side2] - 1 + 'px';
ui.style[props.size[side2]] = tableRect[props.size[side2]] + 'px';
}
// HISTORY
@@ -4580,6 +4574,15 @@ export class OdooEditor extends EventTarget {
}
}
_onScroll(ev) {
if (this._rowUiTarget && !this._rowUi.classList.contains('o_open')) {
this._positionTableUi(this._rowUiTarget);
}
if (this._columnUiTarget && !this._columnUi.classList.contains('o_open')) {
this._positionTableUi(this._columnUiTarget);
}
}
_onDocumentKeydown(ev) {
const canUndoRedo = !['INPUT', 'TEXTAREA'].includes(this.document.activeElement.tagName);
@@ -34,6 +34,12 @@
cursor: pointer !important;
}
}
.o_table_ui_container {
position: absolute;
visibility: hidden;
top: 0;
left: 0;
}
.o_table_ui {
background-color: transparent;
position: absolute;
@@ -46,6 +52,8 @@
}
> div {
position: absolute;
left: 0;
top: 0;
}
.o_table_ui_menu_toggler {
cursor: pointer;