Skip to content

Commit

Permalink
[IMP] web_editor, website: add individual Padding option for grid items
Browse files Browse the repository at this point in the history
Before this commit, the "Padding" grid mode option, added in commit [1],
was impacting all the grid items at the same time, which was not
convenient since all these elements would have the same padding and
could not be styled individually.

This commit improves this option in order to modify the padding of the
grid items individually. The highlight effect, added in commit [2], when
changing the padding is still added.

[1]: odoo@cc406af
[2]: odoo@f3f2c4c

task-3369695

Part-of: odoo#136683
  • Loading branch information
sobo-odoo authored and qsm-odoo committed Oct 14, 2023
1 parent e828683 commit 11418cc
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 66 deletions.
42 changes: 18 additions & 24 deletions addons/web_editor/static/src/js/common/grid_layout_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,23 +163,23 @@ function _placeColumns(columnEls, rowSize, rowGap, columnSize, columnGap) {
let zIndex = 1;
const imageColumns = []; // array of boolean telling if it is a column with only an image.

// Checking if all the columns have a background color to take that into
// account when computing their size and padding (to make them look good).
const allBackgroundColor = [...columnEls].every(columnEl => columnEl.classList.contains('o_cc'));

for (const columnEl of columnEls) {
// Finding out if the images are alone in their column.
let isImageColumn = _checkIfImageColumn(columnEl);
const imageEl = columnEl.querySelector('img');
// Checking if the column has a background color to take that into
// account when computing its size and padding (to make it look good).
const hasBackgroundColor = columnEl.classList.contains("o_cc");
const isImageWithoutPadding = isImageColumn && !hasBackgroundColor;

// Placing the column.
const style = window.getComputedStyle(columnEl);
// Horizontal placement.
const columnLeft = isImageColumn ? imageEl.offsetLeft : columnEl.offsetLeft;
const columnLeft = isImageWithoutPadding ? imageEl.offsetLeft : columnEl.offsetLeft;
// Getting the width of the column.
const paddingLeft = parseFloat(style.paddingLeft);
const width = isImageColumn ? parseFloat(imageEl.scrollWidth)
: parseFloat(columnEl.scrollWidth) - (allBackgroundColor ? 0 : 2 * paddingLeft);
const width = isImageWithoutPadding ? parseFloat(imageEl.scrollWidth)
: parseFloat(columnEl.scrollWidth) - (hasBackgroundColor ? 0 : 2 * paddingLeft);
let columnSpan = Math.round((width + columnGap) / (columnSize + columnGap));
if (columnSpan < 1) {
columnSpan = 1;
Expand All @@ -188,27 +188,30 @@ function _placeColumns(columnEls, rowSize, rowGap, columnSize, columnGap) {
const columnEnd = columnStart + columnSpan;

// Vertical placement.
const columnTop = isImageColumn ? imageEl.offsetTop : columnEl.offsetTop;
const columnTop = isImageWithoutPadding ? imageEl.offsetTop : columnEl.offsetTop;
// Getting the top and bottom paddings and computing the row offset.
const paddingTop = parseFloat(style.paddingTop);
const paddingBottom = parseFloat(style.paddingBottom);
const rowOffsetTop = Math.floor((paddingTop + rowGap) / (rowSize + rowGap));
// Getting the height of the column.
const height = isImageColumn ? parseFloat(imageEl.scrollHeight)
: parseFloat(columnEl.scrollHeight) - (allBackgroundColor ? 0 : paddingTop + paddingBottom);
const height = isImageWithoutPadding ? parseFloat(imageEl.scrollHeight)
: parseFloat(columnEl.scrollHeight) - (hasBackgroundColor ? 0 : paddingTop + paddingBottom);
const rowSpan = Math.ceil((height + rowGap) / (rowSize + rowGap));
const rowStart = Math.round(columnTop / (rowSize + rowGap)) + 1 + (allBackgroundColor || isImageColumn ? 0 : rowOffsetTop);
const rowStart = Math.round(columnTop / (rowSize + rowGap)) + 1 + (hasBackgroundColor || isImageWithoutPadding ? 0 : rowOffsetTop);
const rowEnd = rowStart + rowSpan;

columnEl.style.gridArea = `${rowStart} / ${columnStart} / ${rowEnd} / ${columnEnd}`;
columnEl.classList.add('o_grid_item');

// Adding the grid classes.
columnEl.classList.add('g-col-lg-' + columnSpan, 'g-height-' + rowSpan);

// Setting the initial z-index.
columnEl.style.zIndex = zIndex++;

// Setting the paddings.
if (hasBackgroundColor) {
columnEl.style.setProperty("--grid-item-padding-y", `${paddingTop}px`);
columnEl.style.setProperty("--grid-item-padding-x", `${paddingLeft}px`);
}
// Reload the images.
_reloadLazyImages(columnEl);

Expand All @@ -217,17 +220,6 @@ function _placeColumns(columnEls, rowSize, rowGap, columnSize, columnGap) {
imageColumns.push(isImageColumn);
}

// If all the columns have a background color, set their padding to the
// original padding of the first column.
if (allBackgroundColor) {
const style = window.getComputedStyle(columnEls[0]);
const paddingY = style.paddingTop;
const paddingX = style.paddingLeft;
const rowEl = columnEls[0].parentNode;
rowEl.style.setProperty('--grid-item-padding-y', paddingY);
rowEl.style.setProperty('--grid-item-padding-x', paddingX);
}

for (const [i, columnEl] of [...columnEls].entries()) {
// Removing padding and offset classes.
const regex = /^(pt|pb|col-|offset-)/;
Expand Down Expand Up @@ -304,6 +296,8 @@ export function _convertToNormalColumn(columnEl) {
const gridSizeClasses = columnEl.className.match(/(g-col-lg|g-height)-[0-9]+/g);
columnEl.classList.remove("o_grid_item", "o_grid_item_image", "o_grid_item_image_contain", ...gridSizeClasses);
columnEl.style.removeProperty("z-index");
columnEl.style.removeProperty("--grid-item-padding-x");
columnEl.style.removeProperty("--grid-item-padding-y");
columnEl.style.removeProperty("grid-area");
}
/**
Expand Down
97 changes: 64 additions & 33 deletions addons/web_editor/static/src/js/editor/snippets.options.js
Original file line number Diff line number Diff line change
Expand Up @@ -5111,15 +5111,6 @@ registry.Box = SnippetOptionWidget.extend({


registry.layout_column = SnippetOptionWidget.extend({
/**
* @override
*/
cleanForSave() {
// Remove the padding highlights.
this.$target[0].querySelectorAll('.o_we_padding_highlight').forEach(highlightedEl => {
highlightedEl._removePaddingPreview();
});
},

//--------------------------------------------------------------------------
// Options
Expand Down Expand Up @@ -5266,24 +5257,6 @@ registry.layout_column = SnippetOptionWidget.extend({
gridUtils._resizeGrid(rowEl);
this.trigger_up('activate_snippet', {$snippet: $(newColumnEl)});
},
/**
* @override
*/
async selectStyle(previewMode, widgetValue, params) {
await this._super(...arguments);
if (params.cssProperty.startsWith('--grid-item-padding')) {
// Reset the animations.
this._removePaddingPreview();
void this.$target[0].offsetWidth; // Trigger a DOM reflow.

// Highlight the padding when changing it, by adding a pseudo-
// element with an animated colored border inside the grid items.
const rowEl = this.$target[0];
rowEl.classList.add('o_we_padding_highlight');
rowEl._removePaddingPreview = this._removePaddingPreview.bind(this);
rowEl.addEventListener('animationend', rowEl._removePaddingPreview);
}
},

//--------------------------------------------------------------------------
// Private
Expand Down Expand Up @@ -5381,10 +5354,18 @@ registry.layout_column = SnippetOptionWidget.extend({
* @private
* @param {Element} rowEl
*/
_toggleNormalMode(rowEl) {
async _toggleNormalMode(rowEl) {
// Removing the grid class
rowEl.classList.remove('o_grid_mode');
const columnEls = rowEl.children;
// Removing the grid previews (if any).
await new Promise(resolve => {
this.trigger_up("clean_ui_request", {
targetEl: this.$target[0].closest("section"),
onSuccess: resolve,
});
});

for (const columnEl of columnEls) {
// Reloading the images.
gridUtils._reloadLazyImages(columnEl);
Expand All @@ -5393,20 +5374,70 @@ registry.layout_column = SnippetOptionWidget.extend({
}
// Removing the grid properties.
delete rowEl.dataset.rowCount;
// Kept for compatibility.
rowEl.style.removeProperty('--grid-item-padding-x');
rowEl.style.removeProperty('--grid-item-padding-y');
},
});

registry.GridColumns = SnippetOptionWidget.extend({
/**
* @override
*/
cleanUI() {
// Remove the padding highlights.
this._removePaddingPreview();
},

//--------------------------------------------------------------------------
// Options
//--------------------------------------------------------------------------

/**
* @override
*/
async selectStyle(previewMode, widgetValue, params) {
await this._super(...arguments);
if (["--grid-item-padding-y", "--grid-item-padding-x"].includes(params.cssProperty)) {
// Reset the animation.
this._removePaddingPreview();
void this.$target[0].offsetWidth; // Trigger a DOM reflow.

// Highlight the padding when changing it, by adding a pseudo-
// element with an animated colored border inside the grid item.
this.options.wysiwyg.odooEditor.observerUnactive("addPaddingPreview");
this.$target[0].classList.add("o_we_padding_highlight");
this.options.wysiwyg.odooEditor.observerActive("addPaddingPreview");
this.removePaddingPreview = this._removePaddingPreview.bind(this);
this.$target[0].addEventListener("animationend", this.removePaddingPreview);
}
},

//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------

/**
* @override
*/
_computeWidgetVisibility(widgetName, params) {
if (["grid_padding_y_opt", "grid_padding_x_opt"].includes(widgetName)) {
return this.$target[0].parentElement.classList.contains("o_grid_mode");
}
return this._super(...arguments);
},
/**
* Removes the padding highlights that were added when changing the grid
* items padding.
* item padding.
*
* @private
*/
_removePaddingPreview() {
const rowEl = this.$target[0];
rowEl.removeEventListener('animationend', rowEl._removePaddingPreview);
rowEl.classList.remove('o_we_padding_highlight');
delete rowEl._removePaddingPreview;
this.options.wysiwyg.odooEditor.observerUnactive("removePaddingPreview");
this.$target[0].removeEventListener("animationend", this.removePaddingPreview);
this.$target[0].classList.remove("o_we_padding_highlight");
delete this.removePaddingPreview;
this.options.wysiwyg.odooEditor.observerActive("removePaddingPreview");
},
});

Expand Down
2 changes: 1 addition & 1 deletion addons/web_editor/static/src/scss/wysiwyg_snippets.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2638,7 +2638,7 @@ we-button-group.o_grid we-selection-items {
}
}

.o_we_padding_highlight > .o_grid_item {
.o_we_padding_highlight.o_grid_item {
position: relative;

&::after {
Expand Down
17 changes: 9 additions & 8 deletions addons/website/views/snippets/snippets.xml
Original file line number Diff line number Diff line change
Expand Up @@ -539,10 +539,6 @@
<we-button class="o_we_bg_brand_primary o_grid" data-add-element="text" title="Text" data-name="text">Text</we-button>
<we-button class="o_we_bg_brand_primary o_grid" data-add-element="button" title="Button" data-name="button">Button</we-button>
</we-button-group>
<we-row string="Padding (Y, X)">
<we-input data-dependencies="grid_mode" data-select-style="" data-css-property="--grid-item-padding-y" data-unit="px" data-apply-to=".row"/>
<we-input data-dependencies="grid_mode" data-select-style="" data-css-property="--grid-item-padding-x" data-unit="px" data-apply-to=".row"/>
</we-row>
</div>

<!-- Grid and columns -->
Expand Down Expand Up @@ -570,10 +566,6 @@
<we-button class="o_we_bg_brand_primary o_grid" data-add-element="text" title="Text" data-name="text">Text</we-button>
<we-button class="o_we_bg_brand_primary o_grid" data-add-element="button" title="Button" data-name="button">Button</we-button>
</we-button-group>
<we-row class="o_we_sublevel_1" string="Padding (Y, X)">
<we-input data-dependencies="grid_mode" data-select-style="" data-css-property="--grid-item-padding-y" data-unit="px" data-apply-to=".row"/>
<we-input data-dependencies="grid_mode" data-select-style="" data-css-property="--grid-item-padding-x" data-unit="px" data-apply-to=".row"/>
</we-row>
</div>

<!-- Vertical Alignment -->
Expand Down Expand Up @@ -647,6 +639,15 @@
<t t-set="with_shapes" t-value="True"/>
</t>

<!-- Grid mode columns -->
<div data-js="GridColumns"
data-selector=".row > div">
<we-row string="Padding (Y, X)">
<we-input data-select-style="" data-css-property="--grid-item-padding-y" data-unit="px" data-name="grid_padding_y_opt"/>
<we-input data-select-style="" data-css-property="--grid-item-padding-x" data-unit="px" data-name="grid_padding_x_opt"/>
</we-row>
</div>

<!-- Border | Columns -->
<div data-js="Box"
data-selector="section .row > div"
Expand Down

0 comments on commit 11418cc

Please sign in to comment.