[ADD] web_editor: allow the user to input a font size in the toolbar

With this commit, when a user clicks on the font size number in the
editor's toolbar, two things happen:
1. Same as before: the list of recommended sizes opens.
2. The current font size is selected, and the user can type any value
   they want. They need to confirm with "Enter" or blur the input to use
   a custom value.

task-3167041

Part-of: odoo/odoo#119972
This commit is contained in:
Antoine Guenet
2023-06-16 18:21:46 +02:00
parent c7a5ed99ba
commit 033b49e1a8
5 changed files with 115 additions and 16 deletions
@@ -361,6 +361,19 @@ body.editor_enable.o_basic_theme.o_in_iframe {
top: unset !important;
}
}
#font-size > button {
&:focus-within input {
padding: 0 !important;
width: calc(2ch + #{$o-we-sidebar-content-field-clickable-spacing * 2} - #{$o-we-sidebar-content-field-border-width * 2});
}
input {
padding: 0;
text-align: center;
width: calc(2ch + #{$o-we-sidebar-content-field-clickable-spacing * 2});
}
}
}
}
}
@@ -702,6 +702,59 @@ export class OdooEditor extends EventTarget {
this.updateColorpickerLabels();
});
}
const fontSizeInput = this.toolbar.querySelector('input#fontSizeCurrentValue');
this.addDomListener(this.toolbar, 'click', ev => {
if (fontSizeInput && ev.target.closest('#font-size .dropdown-toggle')) {
// If the click opened the font size dropdown, select the input content.
fontSizeInput.select();
} else if (!this.isSelectionInEditable()) {
// Otherwise, if we lost the selection in the editable, restore it.
this.historyResetLatestComputedSelection(true);
}
})
// Handle the font size input.
if (fontSizeInput) {
const debouncedOnInputChange = (() => {
let handle;
return () => new Promise(resolve => {
clearTimeout(handle);
handle = setTimeout(() => {
handle = null;
setFontSize(fontSizeInput.value);
resolve();
}, 50);
});
})();
const setFontSize = fontSize => {
if (fontSize === 'default' || parseInt(fontSize) > 0) {
if (!this.isSelectionInEditable()) {
this.historyResetLatestComputedSelection(true);
}
this.execCommand('setFontSize', fontSize === 'default' ? undefined : parseInt(fontSize) + 'px');
fontSizeInput.closest('#font-size').querySelectorAll('.show').forEach(el => {
el.classList.remove('show'); // Close the dropdown.
// Remove Popper's styles to ensure proper positioning
// of the dropdown next time it opens.
el.style.removeProperty('inset');
el.style.removeProperty('transform');
});
fontSizeInput.blur();
}
}
this.addDomListener(fontSizeInput, 'change', debouncedOnInputChange);
// Handle the font size dropdown.
const fontSizeDropdown = this.toolbar.querySelector('#font-size');
if (fontSizeDropdown) {
fontSizeDropdown.querySelectorAll('.dropdown-item').forEach(item => {
this.addDomListener(item, 'mousedown', ev => setFontSize(ev.target.textContent));
this.addDomListener(item, 'keydown', ev => {
if (ev.key === 'Enter') {
setFontSize(ev.target.textContent);
}
});
});
}
}
}
resetContent(value) {
@@ -2901,7 +2954,7 @@ export class OdooEditor extends EventTarget {
const fontSizeValue = this.toolbar.querySelector('#fontSizeCurrentValue');
if (fontSizeValue) {
fontSizeValue.textContent = /\d+/.exec(selectionStartStyle.fontSize).pop();
fontSizeValue.value = /\d+/.exec(selectionStartStyle.fontSize).pop();
}
const table = getInSelection(this.document, 'table');
const toolbarButton = this.toolbar.querySelector('.toolbar-edit-table');
@@ -384,6 +384,11 @@ $o-we-zindex: $o-we-overlay-zindex + 1 !default;
@include o-text-overflow();
max-width: 150px;
}
input#fontSizeCurrentValue {
width: 20px;
border: none;
}
}
// Toolbar in Sidebar (website editor, mass mailing)
@@ -516,6 +516,32 @@
padding: ($o-we-sidebar-content-field-height * .12) ($o-we-sidebar-content-field-button-group-button-spacing - 2);
}
#font-size > button {
&:focus-within {
@extend %we-generic-text-input;
// Cancel the height of the border:
margin-top: -1px;
margin-bottom: -1px;
input {
padding: 0 !important;
width: calc(2ch + #{$o-we-sidebar-content-field-clickable-spacing * 2} - #{$o-we-sidebar-content-field-border-width * 2});
}
}
&.dropdown-toggle::after {
display: none;
}
input {
background-color: unset;
border: none;
color: unset;
padding: 0;
text-align: center;
width: calc(2ch + #{$o-we-sidebar-content-field-clickable-spacing * 2});
}
}
we-customizeblock-option {
grid-area: options;
padding-left: 0;
+17 -15
View File
@@ -74,30 +74,32 @@
</div>
</div>
<t t-if="widget.isMobile()"></t>
<t t-if="widget.isMobile()"></t>
<t t-else="">
<div id="font-size" class="btn-group dropdown">
<button type="button" class="btn dropdown-toggle"
data-bs-toggle="dropdown" tabindex="-1"
data-bs-original-title="Font Size" aria-expanded="false">
<span id="fontSizeCurrentValue" title="Font size"></span>
<div id="font-size-input-container">
<input type="text" id="fontSizeCurrentValue" title="Font size" value="13"></input>
</div>
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#" data-call="setFontSize">default</a></li>
<li><a class="dropdown-item" href="#" data-call="setFontSize" data-arg1="8px">8</a></li>
<li><a class="dropdown-item" href="#" data-call="setFontSize" data-arg1="9px">9</a></li>
<li><a class="dropdown-item" href="#" data-call="setFontSize" data-arg1="10px">10</a></li>
<li><a class="dropdown-item" href="#" data-call="setFontSize" data-arg1="11px">11</a></li>
<li><a class="dropdown-item" href="#" data-call="setFontSize" data-arg1="12px">12</a></li>
<li><a class="dropdown-item" href="#" data-call="setFontSize" data-arg1="14px">14</a></li>
<li><a class="dropdown-item" href="#" data-call="setFontSize" data-arg1="18px">18</a></li>
<li><a class="dropdown-item" href="#" data-call="setFontSize" data-arg1="24px">24</a></li>
<li><a class="dropdown-item" href="#" data-call="setFontSize" data-arg1="36px">36</a></li>
<li><a class="dropdown-item" href="#" data-call="setFontSize" data-arg1="48px">48</a></li>
<li><a class="dropdown-item" href="#" data-call="setFontSize" data-arg1="62px">62</a></li>
<li><a class="dropdown-item" href="#">default</a></li>
<li><a class="dropdown-item" href="#">8</a></li>
<li><a class="dropdown-item" href="#">9</a></li>
<li><a class="dropdown-item" href="#">10</a></li>
<li><a class="dropdown-item" href="#">11</a></li>
<li><a class="dropdown-item" href="#">12</a></li>
<li><a class="dropdown-item" href="#">14</a></li>
<li><a class="dropdown-item" href="#">18</a></li>
<li><a class="dropdown-item" href="#">24</a></li>
<li><a class="dropdown-item" href="#">36</a></li>
<li><a class="dropdown-item" href="#">48</a></li>
<li><a class="dropdown-item" href="#">62</a></li>
</ul>
</div>
</t>
</t>
<div id="justify" class="btn-group dropdown">
<button type="button" class="btn dropdown-toggle"