[FIX] web_editor: prevent closestElement traceback with comment nodes

Comment nodes don't have a `closest` method so when passing one to
`closestElement`, the method crashed.

----

Step to reproduce in website:
- Go to debug mode and to website app
- Click on configuration > websites
- Select a website and in the `custom_code_footer` field add an HTML
  comment
- Go to the website and try to enter edit mode -> Crash

The same error will be visible if you simply enter edit mode and drag &
drop the "Code" snippet and enter an HTML comment inside it.

-----

Step to reproduce in marketing automation:
- Install marketing automation
- Click on a campaign > Add a new activity
- On the mail template field, type something > Create and edit
- Select plain text -> `element.closest is not a function`

----

task-3083797
opw-3081323
opw-3081278

closes odoo/odoo#107486

X-original-commit: 3a9177dd6a6f12f75d0df8146b692e3486f2467c
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
This commit is contained in:
Antoine Guenet
2022-12-08 13:38:17 +01:00
parent 515fbccae3
commit 0c2015ee0e
2 changed files with 16 additions and 10 deletions
@@ -1885,7 +1885,7 @@ export class OdooEditor extends EventTarget {
}
if (joinWith) {
const el = closestElement(joinWith);
fillEmpty(el);
el && fillEmpty(el);
}
}
@@ -3462,9 +3462,14 @@ export class OdooEditor extends EventTarget {
*/
isSelectionInEditable(selection) {
selection = selection || this.document.getSelection();
return selection && selection.anchorNode &&
closestElement(selection.anchorNode).isContentEditable && closestElement(selection.focusNode).isContentEditable &&
this.editable.contains(selection.anchorNode) && this.editable.contains(selection.focusNode);
if (selection && selection.anchorNode && selection.focusNode) {
const anchorElement = closestElement(selection.anchorNode);
const focusElement = closestElement(selection.focusNode);
return anchorElement && anchorElement.isContentEditable && focusElement && focusElement.isContentEditable &&
this.editable.contains(selection.anchorNode) && this.editable.contains(selection.focusNode);
} else {
return false;
}
}
/**
* Returns true if the current selection is in at least one block Element
@@ -284,16 +284,17 @@ export function getFurthestUneditableParent(node, parentLimit) {
*
* @param {Node} node
* @param {string} [selector=undefined]
* @param {boolean} [restrictToEditable=false]
* @returns {HTMLElement}
*/
export function closestElement(node, selector) {
const element = node.nodeType === Node.TEXT_NODE ? node.parentElement : node;
if (selector && element) {
const elementFound = element.closest(selector);
return elementFound && elementFound.querySelector('.odoo-editor-editable') ? null : elementFound;
let element = node;
while (element && element.nodeType !== Node.ELEMENT_NODE) {
element = element.parentNode;
}
return selector && element ? element.closest(selector) : element || node;
if (element && selector) {
element = element.closest(selector);
}
return element && element.querySelector('.odoo-editor-editable') ? null : element;
}
/**