summaryrefslogtreecommitdiff
path: root/addons/website/static/src
diff options
context:
space:
mode:
Diffstat (limited to 'addons/website/static/src')
-rw-r--r--addons/website/static/src/js/editor/snippets.editor.js71
1 files changed, 45 insertions, 26 deletions
diff --git a/addons/website/static/src/js/editor/snippets.editor.js b/addons/website/static/src/js/editor/snippets.editor.js
index c5d64e11d54..77229934eac 100644
--- a/addons/website/static/src/js/editor/snippets.editor.js
+++ b/addons/website/static/src/js/editor/snippets.editor.js
@@ -154,37 +154,56 @@ weSnippetEditor.Class.include({
*/
async _onThemeTabClick(ev) {
// Note: nothing async here but start the loading effect asap
- this._execWithLoadingEffect(async () => new Promise(resolve => setTimeout(() => resolve(), 0)), false, 0);
+ let releaseLoader;
+ try {
+ const promise = new Promise(resolve => releaseLoader = resolve);
+ this._execWithLoadingEffect(() => promise, false, 0);
+ // loader is added to the DOM synchronously
+ await new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve)));
+ // ensure loader is rendered: first call asks for the (already done) DOM update,
+ // second call happens only after rendering the first "updates"
- if (!this.topFakeOptionEl) {
- let el;
- for (const [elementName, title] of this.optionsTabStructure) {
- const newEl = document.createElement(elementName);
- newEl.dataset.name = title;
- if (el) {
- el.appendChild(newEl);
- } else {
- this.topFakeOptionEl = newEl;
+ if (!this.topFakeOptionEl) {
+ let el;
+ for (const [elementName, title] of this.optionsTabStructure) {
+ const newEl = document.createElement(elementName);
+ newEl.dataset.name = title;
+ if (el) {
+ el.appendChild(newEl);
+ } else {
+ this.topFakeOptionEl = newEl;
+ }
+ el = newEl;
}
- el = newEl;
+ this.bottomFakeOptionEl = el;
+ this.el.appendChild(this.topFakeOptionEl);
}
- this.bottomFakeOptionEl = el;
- this.el.appendChild(this.topFakeOptionEl);
- }
- // Need all of this in that order so that:
- // - the element is visible and can be enabled and the onFocus method is
- // called each time.
- // - the element is hidden afterwards so it does not take space in the
- // DOM, same as the overlay which may make a scrollbar appear.
- this.topFakeOptionEl.classList.remove('d-none');
- const editor = await this._activateSnippet($(this.bottomFakeOptionEl));
- this.topFakeOptionEl.classList.add('d-none');
- editor.toggleOverlay(false);
+ // Need all of this in that order so that:
+ // - the element is visible and can be enabled and the onFocus method is
+ // called each time.
+ // - the element is hidden afterwards so it does not take space in the
+ // DOM, same as the overlay which may make a scrollbar appear.
+ this.topFakeOptionEl.classList.remove('d-none');
+ const editorPromise = this._activateSnippet($(this.bottomFakeOptionEl));
+ releaseLoader(); // because _activateSnippet uses the same mutex as the loader
+ releaseLoader = undefined;
+ const editor = await editorPromise;
+ this.topFakeOptionEl.classList.add('d-none');
+ editor.toggleOverlay(false);
- this._updateLeftPanelContent({
- tab: this.tabs.THEME,
- });
+ this._updateLeftPanelContent({
+ tab: this.tabs.THEME,
+ });
+ } catch (e) {
+ // Normally the loading effect is removed in case of error during the action but here
+ // the actual activity is happening outside of the action, the effect must therefore
+ // be cleared in case of error as well
+ if (releaseLoader) {
+ releaseLoader();
+ }
+ throw e;
+ }
},
});