Skip to content

Commit a3bb744

Browse files
committed
ScrollButton
1 parent 5f89054 commit a3bb744

File tree

4 files changed

+158
-1
lines changed

4 files changed

+158
-1
lines changed

addons/html_builder/static/src/utils/utils_css.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,7 @@ export function applyNeededCss(
600600
{ force = false, allowImportant = true } = {}
601601
) {
602602
if (force) {
603-
el.style.setProperty(cssProp, cssValue, "important");
603+
el.style.setProperty(cssProp, cssValue, allowImportant ? "important" : "");
604604
return true;
605605
}
606606
el.style.removeProperty(cssProp);
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { BaseOptionComponent, useDomState } from "@html_builder/core/utils";
2+
import { _t } from "@web/core/l10n/translation";
3+
4+
export class ScrollButtonOption extends BaseOptionComponent {
5+
static template = "html_builder.ScrollButtonOption";
6+
static props = {};
7+
8+
setup() {
9+
super.setup();
10+
this.state = useDomState((editingElement) => ({
11+
heightLabel:
12+
editingElement.dataset.snippet === "s_image_gallery"
13+
? _t("Min-Height")
14+
: _t("Height"),
15+
heightFieldEnabled: editingElement.dataset.snippet === "s_image_gallery",
16+
}));
17+
}
18+
19+
showHeightField() {
20+
return this.state.heightFieldEnabled && this.isActiveItem("fit_content_opt");
21+
}
22+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<templates xml:space="preserve">
3+
4+
<t t-name="html_builder.ScrollButtonOption">
5+
<BuilderRow label="this.state.heightLabel">
6+
<BuilderButtonGroup action="'scrollButtonSectionHeightClassAction'">
7+
<BuilderButton id="'fit_content_opt'" actionParam="''" title.translate="Fit content">Auto</BuilderButton>
8+
<BuilderButton actionParam="'o_half_screen_height'" title.translate="Half screen">50%</BuilderButton>
9+
<BuilderButton id="'full_height_opt'" actionParam="'o_full_screen_height'" title.translate="Full screen">100%</BuilderButton>
10+
</BuilderButtonGroup>
11+
</BuilderRow>
12+
13+
<BuilderRow label.translate="Height" level="1" t-if="this.showHeightField()">
14+
<BuilderNumberInput styleAction="{ mainParam: 'height', force: true, allowImportant: false }" unit="'px'" min="0"/>
15+
</BuilderRow>
16+
17+
<BuilderRow label.translate="Scroll Down Button" t-if="this.isActiveItem('full_height_opt')">
18+
<BuilderCheckbox id="'scroll_button_opt'" action="'addScrollButton'"/>
19+
</BuilderRow>
20+
21+
<t t-if="this.isActiveItem('scroll_button_opt')">
22+
<BuilderRow label.translate="Colors" level="1" applyTo="':scope > .o_scroll_button'">
23+
<BuilderColorPicker styleAction="'background-color'"/>
24+
<BuilderColorPicker styleAction="'color'"/>
25+
</BuilderRow>
26+
<BuilderRow label.translate="Spacing" level="1" applyTo="':scope > .o_scroll_button'">
27+
<BuilderSelect>
28+
<BuilderSelectItem classAction="''">None</BuilderSelectItem>
29+
<BuilderSelectItem classAction="'mb-1'">Extra-Small</BuilderSelectItem>
30+
<BuilderSelectItem classAction="'mb-2'">Small</BuilderSelectItem>
31+
<BuilderSelectItem classAction="'mb-3'">Medium</BuilderSelectItem>
32+
<BuilderSelectItem classAction="'mb-4'">Large</BuilderSelectItem>
33+
<BuilderSelectItem classAction="'mb-5'">Extra-Large</BuilderSelectItem>
34+
</BuilderSelect>
35+
</BuilderRow>
36+
</t>
37+
</t>
38+
39+
</templates>
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import { Plugin } from "@html_editor/plugin";
2+
import { _t } from "@web/core/l10n/translation";
3+
import { registry } from "@web/core/registry";
4+
import { ScrollButtonOption } from "./scroll_button_option";
5+
import { classAction } from "@html_builder/core/core_builder_action_plugin";
6+
7+
class ScrollButtonOptionPlugin extends Plugin {
8+
static id = "scrollButtonOption";
9+
resources = {
10+
builder_options: [
11+
{
12+
OptionComponent: ScrollButtonOption,
13+
selector: "section",
14+
exclude:
15+
"[data-snippet] :not(.oe_structure) > [data-snippet],.s_instagram_page,.o_mega_menu > section,.s_appointments .s_dynamic_snippet_content",
16+
},
17+
],
18+
builder_actions: {
19+
addScrollButton: {
20+
isApplied: ({ editingElement }) =>
21+
!!editingElement.querySelector(":scope > .o_scroll_button"),
22+
apply: ({ editingElement }) => {
23+
let button = this.buttonCache.get(editingElement);
24+
if (!button) {
25+
const anchor = document.createElement("a");
26+
anchor.classList.add(
27+
"o_scroll_button",
28+
"mb-3",
29+
"rounded-circle",
30+
"align-items-center",
31+
"justify-content-center",
32+
"mx-auto",
33+
"bg-primary",
34+
"o_not_editable"
35+
);
36+
anchor.href = "#";
37+
anchor.contentEditable = "false";
38+
anchor.title = _t("Scroll down to next section");
39+
const arrow = document.createElement("i");
40+
arrow.classList.add("fa", "fa-angle-down", "fa-3x");
41+
anchor.appendChild(arrow);
42+
button = anchor;
43+
this.buttonCache.set(editingElement, button);
44+
}
45+
editingElement.appendChild(button);
46+
},
47+
clean: this.removeButton.bind(this),
48+
},
49+
scrollButtonSectionHeightClassAction: {
50+
...classAction,
51+
apply: (args) => {
52+
classAction.apply(args);
53+
const {
54+
editingElement,
55+
param: { mainParam },
56+
} = args;
57+
// If a "d-lg-block" class exists on the section (e.g., for
58+
// mobile visibility option), it should be replaced with a
59+
// "d-lg-flex" class. This ensures that the section has the
60+
// "display: flex" property applied, which is the default
61+
// rule for both "height" option classes.
62+
if (mainParam) {
63+
editingElement.classList.replace("d-lg-block", "d-lg-flex");
64+
} else if (editingElement.classList.contains("d-lg-flex")) {
65+
// There are no known cases, but we still make sure that
66+
// the <section> element doesn't have a "display: flex"
67+
// originally.
68+
editingElement.classList.remove("d-lg-flex");
69+
const sectionStyle = window.getComputedStyle(editingElement);
70+
const hasDisplayFlex = sectionStyle.getPropertyValue("display") === "flex";
71+
editingElement.classList.add(hasDisplayFlex ? "d-lg-flex" : "d-lg-block");
72+
}
73+
},
74+
clean: (args) => {
75+
classAction.clean(args);
76+
if (args.param.mainParam === "o_full_screen_height") {
77+
this.removeButton(args);
78+
}
79+
},
80+
},
81+
},
82+
};
83+
84+
setup() {
85+
this.buttonCache = new Map();
86+
}
87+
88+
removeButton({ editingElement }) {
89+
const button = editingElement.querySelector(":scope > .o_scroll_button");
90+
if (button) {
91+
button.remove();
92+
this.buttonCache.set(editingElement, button);
93+
}
94+
}
95+
}
96+
registry.category("website-plugins").add(ScrollButtonOptionPlugin.id, ScrollButtonOptionPlugin);

0 commit comments

Comments
 (0)