diff --git a/addons/web_editor/static/src/js/wysiwyg/widgets/link.js b/addons/web_editor/static/src/js/wysiwyg/widgets/link.js index 5c881e71d0e..75b305c4b04 100644 --- a/addons/web_editor/static/src/js/wysiwyg/widgets/link.js +++ b/addons/web_editor/static/src/js/wysiwyg/widgets/link.js @@ -31,8 +31,6 @@ const Link = Widget.extend({ title: _t("Link to"), }, this.options)); - this._setLinkContent = true; - this.data = data || {}; this.isButton = this.data.isButton; this.$button = $button; @@ -86,7 +84,7 @@ const Link = Widget.extend({ $node = $node.parent(); } const linkNode = this.$link[0] || this.data.range.cloneContents(); - const linkText = linkNode.textContent; + const linkText = linkNode.innerText; this.data.content = linkText.replace(/[ \t\r\n]+/g, ' '); this.data.originalText = this.data.content; if (linkNode instanceof DocumentFragment) { @@ -488,11 +486,19 @@ const Link = Widget.extend({ * @param {boolean} force */ _updateLinkContent($link, linkInfos, { force = false } = {}) { - if (force || (this._setLinkContent && (linkInfos.content !== this.data.originalText || linkInfos.url !== this.data.url))) { + if (force || (linkInfos.content !== this.data.originalText || linkInfos.url !== this.data.url)) { if (linkInfos.content === this.data.originalText) { $link.html(this.data.originalHTML); } else if (linkInfos.content && linkInfos.content.length) { - $link.text(linkInfos.content); + let contentWrapperEl = $link[0]; + // Update the first child element that has the same inner text + // as the link with the new content while preserving child + // elements within the link. (e.g. the link is bold and italic) + while (contentWrapperEl.firstElementChild + && (contentWrapperEl.firstElementChild.innerText === $link[0].innerText)) { + contentWrapperEl = contentWrapperEl.firstElementChild; + } + contentWrapperEl.innerText = linkInfos.content; } else { $link.text(linkInfos.url); } diff --git a/addons/web_editor/static/src/js/wysiwyg/widgets/link_tools.js b/addons/web_editor/static/src/js/wysiwyg/widgets/link_tools.js index b6cee090e9a..99160708d92 100644 --- a/addons/web_editor/static/src/js/wysiwyg/widgets/link_tools.js +++ b/addons/web_editor/static/src/js/wysiwyg/widgets/link_tools.js @@ -23,6 +23,7 @@ const LinkTools = Link.extend({ 'change .link-custom-color-border input': '_onChangeCustomBorderWidth', 'keypress .link-custom-color-border input': '_onKeyPressCustomBorderWidth', 'click we-select [name="link_border_style"] we-button': '_onBorderStyleSelectOption', + 'input input[name="label"]': '_onLabelInput', }), /** @@ -31,8 +32,7 @@ const LinkTools = Link.extend({ init: function (parent, options, editable, data, $button, link) { this._link = link; this._observer = new MutationObserver(() =>{ - this._setLinkContent = false; - this._observer.disconnect(); + this._updateLabelInput(); }); this._observer.observe(this._link, {subtree: true, childList: true, characterData: true}); this._super(parent, options, editable, data, $button, this._link); @@ -358,6 +358,14 @@ const LinkTools = Link.extend({ this.$button.removeClass('active'); this.options.wysiwyg.odooEditor.observerActive("hint_classes"); }, + /** + * Updates the label input with the DOM content of the link. + * + * @private + */ + _updateLabelInput() { + this.el.querySelector('#o_link_dialog_label_input').value = this.linkEl.innerText; + }, //-------------------------------------------------------------------------- // Handlers @@ -440,6 +448,23 @@ const LinkTools = Link.extend({ this._adaptPreview(); this.options.wysiwyg.odooEditor.historyUnpauseSteps('_onURLInput'); }, + /** + * Updates the DOM content of the link with the input value. + * + * @private + * @param {Event} ev + */ + _onLabelInput(ev) { + const data = this._getData(); + if (!data) { + return; + } + this._observer.disconnect(); + // Force update of link's content with new data using 'force: true'. + // Without this, no update if input is same as original text. + this._updateLinkContent(this.$link, data, {force: true}); + this._observer.observe(this._link, {subtree: true, childList: true, characterData: true}); + }, }); return LinkTools; diff --git a/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js b/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js index e758e3b0cb2..0541879604c 100644 --- a/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js +++ b/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js @@ -1185,9 +1185,13 @@ const Wysiwyg = Widget.extend({ startNode: options.link || this.lastMediaClicked, }); if (!link) { - return + return; } - const linkToolsData = Object.assign({}, this.options.defaultDataForLinkTools); + const linkToolsData = Object.assign({}, this.options.defaultDataForLinkTools, { + // If the link contains an image or an icon do not + // display the label input (e.g. some mega menu links). + needLabel: !link.querySelector('.fa, img'), + }); this.linkTools = new weWidgets.LinkTools(this, { wysiwyg: this, noFocusUrl: options.noFocusUrl, diff --git a/addons/web_editor/static/src/xml/wysiwyg.xml b/addons/web_editor/static/src/xml/wysiwyg.xml index 2b92ae3a0ac..3030b377ea6 100644 --- a/addons/web_editor/static/src/xml/wysiwyg.xml +++ b/addons/web_editor/static/src/xml/wysiwyg.xml @@ -184,14 +184,6 @@ - - Link Label - -
- -
-
-
@@ -208,6 +200,14 @@ + + Label + +
+ +
+
+
Style diff --git a/addons/website/static/tests/tours/link_tools.js b/addons/website/static/tests/tours/link_tools.js index f365c6a477a..0ccdcd45186 100644 --- a/addons/website/static/tests/tours/link_tools.js +++ b/addons/website/static/tests/tours/link_tools.js @@ -34,10 +34,33 @@ wTourUtils.registerWebsitePreviewTour('link_tools', { clickOnImgStep, // 2. Edit the link with the link tools. { - content: "Click on the newly created link, change content to odoo website", + content: "Click on the newly created link", trigger: 'iframe .s_text_image a[href="http://odoo.com"]:contains("odoo.com")', + }, + { + content: "Change content (editing the label input) to odoo website_2", + trigger: '#o_link_dialog_label_input[value="odoo.com"]', + run: 'text odoo website_2', + }, + { + content: "Click again on the link", + trigger: 'iframe .s_text_image a[href="http://odoo.com"]:contains("odoo website_2")', + }, + { + content: "Change content (editing the DOM) to odoo website", + trigger: 'iframe .s_text_image a[href="http://odoo.com"]:contains("odoo website_2")', run: 'text odoo website', }, + clickOnImgStep, + { + content: "Click again on the link", + trigger: 'iframe .s_text_image a[href="http://odoo.com"]:contains("odoo website")', + }, + { + content: "Check that the label input contains the new content", + trigger: '#o_link_dialog_label_input[value="odoo website"]', + run: () => null, // it's a check + }, { content: "Link tools, should be open, change the url", trigger: '#o_link_dialog_url_input',