Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions addons/html_builder/static/src/core/utils/update_on_img_changed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { Component, onWillStart, xml } from "@odoo/owl";
import { useDomState } from "../utils";

class LoadImgComponent extends Component {
static template = xml`
<t t-slot="default"/>
`;
static props = { slots: { type: Object } };

setup() {
onWillStart(async () => {
const editingElements = this.env.getEditingElements();
const promises = [];
for (const editingEl of editingElements) {
const imageEls = editingEl.matches("img")
? [editingEl]
: editingEl.querySelectorAll("img");
for (const imageEl of imageEls) {
if (!imageEl.complete) {
promises.push(
new Promise((resolve) => {
imageEl.addEventListener("load", () => resolve());
})
);
}
}
}
await Promise.all(promises);
});
}
}

/**
* In Chrome, when replacing an image on the DOM, some image properties are not
* available even if the image has been loaded beforehand. This is a problem if
* an option is using one of those property at each DOM change (useDomState).
* To solve the problem, this component reloads the option (and waits for the
* images to be loaded) each time an image has been modified inside its editing
* element.
*/
export class UpdateOptionOnImgChanged extends Component {
// TODO: this is a hack until <t t-key="state.count" t-slot="default"/> is
// fixed in OWL.
static template = xml`
<LoadImgComponent t-if="state.bool"><t t-slot="default"/></LoadImgComponent>
<LoadImgComponent t-else=""><t t-slot="default"/></LoadImgComponent>
`;
static props = { slots: { type: Object } };
static components = { LoadImgComponent };

setup() {
let boolean = true;
this.state = useDomState((editingElement) => {
const imageEls = editingElement.matches("img")
? [editingElement]
: editingElement.querySelectorAll("img");
for (const imageEl of imageEls) {
if (!imageEl.complete) {
// Rerender the slot if an image is not loaded
boolean = !boolean;
break;
}
}
return {
bool: boolean,
};
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { WebsiteBackgroundOption } from "@html_builder/website_builder/plugins/o
import { CardImageOption } from "./card_image_option";
import { BorderConfigurator } from "@html_builder/plugins/border_configurator_option";
import { ShadowOption } from "@html_builder/plugins/shadow_option";
import { UpdateOptionOnImgChanged } from "@html_builder/core/utils/update_on_img_changed";

export class CardOption extends BaseOptionComponent {
static template = "website.CardOption";
Expand All @@ -11,6 +12,7 @@ export class CardOption extends BaseOptionComponent {
WebsiteBackgroundOption,
BorderConfigurator,
ShadowOption,
UpdateOptionOnImgChanged,
};
static props = {
disableWidth: { type: Boolean, optional: true },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
<BorderConfigurator label.translate="Border"/>
<ShadowOption/>
<t t-if="!this.props.disableWidth" t-call="website.CardWidthOption"/>
<CardImageOption/>
<UpdateOptionOnImgChanged>
<CardImageOption/>
</UpdateOptionOnImgChanged>
</t>

</templates>