[IMP] web_editor, website: adds label input to links in the editor panel
This commit adds a new feature to the web editor of a website. A "text" input field has been added to the link editor panel, allowing users to edit the label of a link. The label will only be updated when the input is changed, to prevent loss of formatting (e.g. if one letter is bold). However, only formatting applied to the entire selection will be kept (e.g. if you have a "link <b>like</b> this", nothing will be in bold if you update the label in the editor panel). Additionally, if there is a media element (such as an image or icon) included in the selection, the "text" input will be hidden. task-2900529 closes odoo/odoo#99239 Signed-off-by: Benoit Socias (bso) <bso@odoo.com>
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -184,14 +184,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<we-customizeblock-option t-name="wysiwyg.widgets.linkTools">
|
||||
<we-row t-attf-class="o_we_sublevel_1 {{widget.needLabel ? '' : 'd-none'}}">
|
||||
<we-title>Link Label</we-title>
|
||||
<we-input class="o_we_user_value_widget">
|
||||
<div>
|
||||
<input name="label" id="o_link_dialog_label_input" t-att-value="widget.data.content" type="text"/>
|
||||
</div>
|
||||
</we-input>
|
||||
</we-row>
|
||||
<we-row id="url_row" t-attf-class="#{widget.isButton ? ' d-none' : ''}">
|
||||
<we-input class="o_we_user_value_widget o_we_sublevel_1">
|
||||
<we-title class="o_short_title"></we-title>
|
||||
@@ -208,6 +200,14 @@
|
||||
</div>
|
||||
</we-button>
|
||||
</we-row>
|
||||
<we-row t-attf-class="o_we_sublevel_1 {{widget.needLabel ? '' : 'd-none'}}">
|
||||
<we-title>Label</we-title>
|
||||
<we-input class="o_we_user_value_widget">
|
||||
<div>
|
||||
<input name="label" id="o_link_dialog_label_input" t-att-value="widget.data.content" type="text"/>
|
||||
</div>
|
||||
</we-input>
|
||||
</we-row>
|
||||
<we-row>
|
||||
<we-select class="o_we_user_value_widget o_we_sublevel_1">
|
||||
<we-title>Style</we-title>
|
||||
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user