[IMP] web_editor: use o_editable and o_not_editable as markers
Before this commit, the o_not_editable class was used as a way to dynamically set contentEditable on a node. This was little more than a convulated way to write `node.contentEditable = false`. Moreover, the o_editable class was not treated the same way and did not set contentEditable to true. This commit turns those two classes into markers for contentEditable values in html. Once those classes are set, the contentEditable attribute is updated accordingly. It is not updated dynamically afterwards. For dynamically setting a node as editable or not, use the contentEditable attribute directly. Task-2782426 Part-of: odoo/odoo#120690
This commit is contained in:
committed by
David Beguin
parent
82985296e1
commit
17ee75a84d
@@ -3051,9 +3051,6 @@ var SnippetsMenu = Widget.extend({
|
||||
// Register the text nodes that needs to be auto-selected on click
|
||||
this._registerDefaultTexts();
|
||||
|
||||
// Force non editable part to contentEditable=false
|
||||
$html.find('.o_not_editable').attr('contentEditable', false);
|
||||
|
||||
// Add the computed template and make elements draggable
|
||||
this.$el.html($html);
|
||||
this.$el.append(this.customizePanel);
|
||||
|
||||
@@ -109,7 +109,6 @@ const Wysiwyg = Widget.extend({
|
||||
this._signalOnline = this._signalOnline.bind(this);
|
||||
this.tooltipTimeouts = [];
|
||||
Wysiwyg.activeWysiwygs.add(this);
|
||||
this._oNotEditableObservers = new Map();
|
||||
this._joinPeerToPeer = this._joinPeerToPeer.bind(this);
|
||||
},
|
||||
/**
|
||||
@@ -178,7 +177,7 @@ const Wysiwyg = Widget.extend({
|
||||
document: this.options.document,
|
||||
autohideToolbar: !!this.options.autohideToolbar,
|
||||
isRootEditable: this.options.isRootEditable,
|
||||
onPostSanitize: this._setONotEditable.bind(this),
|
||||
onPostSanitize: this._onPostSanitize.bind(this),
|
||||
placeholder: this.options.placeholder,
|
||||
powerboxFilters: this.options.powerboxFilters || [],
|
||||
showEmptyElementHint: this.options.showEmptyElementHint,
|
||||
@@ -409,12 +408,12 @@ const Wysiwyg = Widget.extend({
|
||||
this.setCSSVariables(this.snippetsMenu ? this.snippetsMenu.el : this.toolbar.el);
|
||||
|
||||
this.odooEditor.addEventListener('preObserverActive', () => {
|
||||
// The setONotEditable will be called right after the
|
||||
// The onPostSanitize will be called right after the
|
||||
// editor sanitization (to be right before the historyStep).
|
||||
// If any `.o_not_editable` is created while the observer is
|
||||
// unactive, now is the time to call `setONotEditable` before the
|
||||
// unactive, now is the time to call `onPostSanitize` before the
|
||||
// editor could register a mutation.
|
||||
this._setONotEditable(this.odooEditor.editable);
|
||||
this._onPostSanitize(this.odooEditor.editable);
|
||||
});
|
||||
|
||||
if (this.options.autohideToolbar) {
|
||||
@@ -716,9 +715,6 @@ const Wysiwyg = Widget.extend({
|
||||
this.odooEditor.document.removeEventListener("keydown", this._signalOnline, true);
|
||||
this.odooEditor.document.removeEventListener("keyup", this._signalOnline, true);
|
||||
this.odooEditor.document.removeEventListener('selectionchange', this._onSelectionChange);
|
||||
for (const observer of this._oNotEditableObservers.values()) {
|
||||
observer.disconnect();
|
||||
}
|
||||
this.odooEditor.destroy();
|
||||
}
|
||||
// If peer to peer is initializing, wait for properly closing it.
|
||||
@@ -2680,40 +2676,17 @@ const Wysiwyg = Widget.extend({
|
||||
await this._peerToPeerLoading;
|
||||
},
|
||||
/**
|
||||
* Set contenteditable=false for all `.o_not_editable` found within node if
|
||||
* node is an element.
|
||||
*
|
||||
* For all `.o_not_editable` element found, the attribute contenteditable
|
||||
* will be removed if the class is removed.
|
||||
* Set `contenteditable` according to `.o_not_editable` and `.o_editable`.
|
||||
*
|
||||
* @param {Node} node
|
||||
*/
|
||||
_setONotEditable: function (node) {
|
||||
const nodes = (node && node.querySelectorAll && node.querySelectorAll('.o_not_editable:not([contenteditable=false])')) || [];
|
||||
for (const node of nodes) {
|
||||
node.setAttribute('contenteditable', false);
|
||||
let observer = this._oNotEditableObservers.get(node);
|
||||
if (!observer) {
|
||||
observer = new MutationObserver((records) => {
|
||||
for (const record of records) {
|
||||
if (record.type === 'attributes' && record.attributeName === 'class') {
|
||||
// Remove contenteditable=false on nodes that were
|
||||
// previsouly o_not_editable but are no longer
|
||||
// o_not_editable.
|
||||
if (!node.classList.contains('o_not_editable')) {
|
||||
this.odooEditor.observerUnactive('_setONotEditable');
|
||||
node.removeAttribute('contenteditable');
|
||||
this.odooEditor.observerActive('_setONotEditable');
|
||||
observer.disconnect();
|
||||
this._oNotEditableObservers.delete(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
this._oNotEditableObservers.set(node, observer);
|
||||
observer.observe(node, {
|
||||
attributes: true,
|
||||
});
|
||||
_onPostSanitize: function (node) {
|
||||
if (node?.querySelectorAll) {
|
||||
for (const element of node.querySelectorAll('.o_editable, .o_not_editable')) {
|
||||
const editable = element.classList.contains('o_editable');
|
||||
if (element.isContentEditable !== editable) {
|
||||
element.contentEditable = editable;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -71,6 +71,7 @@ wTourUtils.registerWebsitePreviewTour('link_tools', {
|
||||
...wTourUtils.clickOnSave(),
|
||||
// 3. Edit a link after saving the page.
|
||||
...wTourUtils.clickOnEditAndWaitEditMode(),
|
||||
clickOnImgStep,
|
||||
{
|
||||
content: "The new link content should be odoo website and url odoo.be",
|
||||
trigger: 'iframe .s_text_image a[href="http://odoo.be"]:contains("odoo website")',
|
||||
|
||||
Reference in New Issue
Block a user