[REF] web_editor, website: add utility functions isMobileView()

This commit implements two generic utility functions with similar
behavior that check whether the view is mobile or desktop:
- For web_editor: depending on the view of the targeted element
- For website: depending on the context

task-3097045

Part-of: odoo/odoo#117562
This commit is contained in:
Robin Lejeune (role)
2023-10-20 19:12:43 +00:00
committed by qsm-odoo
parent d6cb0e8797
commit d210af8348
7 changed files with 54 additions and 22 deletions
@@ -1,5 +1,6 @@
/** @odoo-module **/
import {SIZES, MEDIAS_BREAKPOINTS} from "@web/core/ui/ui_service";
import {
normalizeCSSColor,
isCSSColor,
@@ -462,6 +463,18 @@ function _shouldEditableMediaBeEditable(mediaEl) {
&& nonEditableAncestorRootEl.parentElement
&& nonEditableAncestorRootEl.parentElement.isContentEditable;
}
/**
* Checks if the view of the targeted element is mobile.
*
* @param {HTMLElement} targetEl - target of the editor
* @returns {boolean}
*/
function _isMobileView(targetEl) {
const mobileViewThreshold = MEDIAS_BREAKPOINTS[SIZES.LG].minWidth;
const clientWidth = targetEl.ownerDocument.defaultView?.frameElement?.clientWidth ||
targetEl.ownerDocument.documentElement.clientWidth;
return clientWidth && clientWidth < mobileViewThreshold;
}
export default {
COLOR_PALETTE_COMPATIBILITY_COLOR_NAMES: COLOR_PALETTE_COMPATIBILITY_COLOR_NAMES,
@@ -488,4 +501,5 @@ export default {
addBackgroundImageAttributes: _addBackgroundImageAttributes,
isBackgroundImageAttribute: _isBackgroundImageAttribute,
shouldEditableMediaBeEditable: _shouldEditableMediaBeEditable,
isMobileView: _isMobileView,
};
@@ -2513,7 +2513,7 @@ var SnippetsMenu = Widget.extend({
this.invisibleDOMMap = new Map();
const $invisibleDOMPanelEl = $(this.invisibleDOMPanelEl);
$invisibleDOMPanelEl.find('.o_we_invisible_entry').remove();
const isMobile = this.options.wysiwyg.websiteService?.context.isMobile;
const isMobile = this._isMobile();
const invisibleSelector = `.o_snippet_invisible, ${isMobile ? '.o_snippet_mobile_invisible' : '.o_snippet_desktop_invisible'}`;
const $selector = this.options.enableTranslation ? this.$body : globalSelector.all();
let $invisibleSnippets = $selector.find(invisibleSelector).addBack(invisibleSelector);
@@ -3680,6 +3680,14 @@ var SnippetsMenu = Widget.extend({
Tooltip.getInstance(el)?.hide();
}
},
/**
* Returns whether the edited content is a mobile view content.
*
* @returns {boolean}
*/
_isMobile() {
return weUtils.isMobileView(this.$body[0]);
},
//--------------------------------------------------------------------------
// Handlers
@@ -31,7 +31,6 @@ import {
getDataURLBinarySize,
} from "@web_editor/js/editor/image_processing";
import * as OdooEditorLib from "@web_editor/js/editor/odoo-editor/src/OdooEditor";
import {SIZES, MEDIAS_BREAKPOINTS} from "@web/core/ui/ui_service";
import { pick } from "@web/core/utils/objects";
import { _t } from "@web/core/l10n/translation";
import {
@@ -4013,8 +4012,7 @@ const SnippetOptionWidget = Widget.extend({
if (moveUpOrLeft || moveDownOrRight) {
// The arrows are not displayed if the target is in a grid and if
// not in mobile view.
const mobileViewThreshold = MEDIAS_BREAKPOINTS[SIZES.LG].minWidth;
const isMobileView = this.$target[0].ownerDocument.defaultView.frameElement.clientWidth < mobileViewThreshold;
const isMobileView = weUtils.isMobileView(this.$target[0]);
if (this.$target[0].classList.contains('o_grid_item') && !isMobileView) {
return false;
}
@@ -4683,8 +4681,7 @@ registry.sizing = SnippetOptionWidget.extend({
async updateUIVisibility() {
await this._super(...arguments);
const mobileViewThreshold = MEDIAS_BREAKPOINTS[SIZES.LG].minWidth;
const isMobileView = this.$target[0].ownerDocument.defaultView.frameElement.clientWidth < mobileViewThreshold;
const isMobileView = weUtils.isMobileView(this.$target[0]);
const isGrid = this.$target[0].classList.contains('o_grid_item');
if (this.$target[0].parentNode && this.$target[0].parentNode.classList.contains('row')) {
// Hiding/showing the correct resize handles if we are in grid mode
@@ -5280,8 +5277,7 @@ registry.layout_column = SnippetOptionWidget.extend({
await this._super(previewMode, widgetValue, params);
const rowEl = this.$target[0];
const mobileViewThreshold = MEDIAS_BREAKPOINTS[SIZES.LG].minWidth;
const isMobileView = rowEl.ownerDocument.defaultView.frameElement.clientWidth < mobileViewThreshold;
const isMobileView = weUtils.isMobileView(rowEl);
if (["row-gap", "column-gap"].includes(params.cssProperty) && !isMobileView) {
// Reset the animation.
this._removeGridPreview();
@@ -8025,10 +8021,7 @@ registry.BackgroundShape = SnippetOptionWidget.extend({
shapeToSelect = possibleShapes[1];
}
// Only show on mobile by default if toggled from mobile view
const mobileViewThreshold = MEDIAS_BREAKPOINTS[SIZES.LG].minWidth;
const isMobileView = this.$target[0].ownerDocument
.defaultView.frameElement.clientWidth < mobileViewThreshold;
const showOnMobile = isMobileView;
const showOnMobile = weUtils.isMobileView(this.$target[0]);
this.trigger_up('snippet_edition_request', {exec: () => {
// options for shape will only be available after _toggleShape() returned
this._requestUserValueWidgets('bg_shape_opt')[0].enable();
@@ -4,6 +4,7 @@ import { _t } from "@web/core/l10n/translation";
import Dialog from "@web/legacy/js/core/dialog";
import weSnippetEditor from "@web_editor/js/editor/snippets.editor";
import wSnippetOptions from "@website/js/editor/snippets.options";
import wUtils from "@website/js/utils";
import * as OdooEditorLib from "@web_editor/js/editor/odoo-editor/src/utils/utils";
import { renderToElement } from "@web/core/utils/render";
const getDeepRange = OdooEditorLib.getDeepRange;
@@ -302,6 +303,12 @@ const wSnippetMenu = weSnippetEditor.SnippetsMenu.extend({
_isValidSelection(sel) {
return sel.rangeCount && [...this.getEditableArea()].some(el => el.contains(sel.anchorNode));
},
/**
* @override
*/
_isMobile() {
return wUtils.isMobile(this);
},
//--------------------------------------------------------------------------
// Handlers
@@ -2583,12 +2583,7 @@ options.registry.DeviceVisibility = options.Class.extend({
}
// Update invisible elements.
let isMobile;
this.trigger_up('service_context_get', {
callback: (ctx) => {
isMobile = ctx['isMobile'];
},
});
const isMobile = wUtils.isMobile(this);
this.trigger_up('snippet_option_visibility_update', {show: widgetValue !== (isMobile ? 'no_mobile' : 'no_desktop')});
},
/**
+18
View File
@@ -416,6 +416,23 @@ export function generateGMapLink(dataset) {
+ '&ie=UTF8&iwloc=&output=embed';
}
/**
* Checks if the edited content is currently previewed as in a mobile device.
*
* @param {Object} self - context object ("this")
* @returns {boolean}
*/
function isMobile(self) {
let isMobile;
self.trigger_up("service_context_get", {
callback: (ctx) => {
isMobile = ctx["isMobile"];
},
});
return isMobile;
}
export default {
loadAnchors: loadAnchors,
autocompleteWithPages: autocompleteWithPages,
@@ -427,4 +444,5 @@ export default {
svgToPNG: svgToPNG,
generateGMapIframe: generateGMapIframe,
generateGMapLink: generateGMapLink,
isMobile: isMobile,
};
@@ -2,7 +2,6 @@
import options from '@web_editor/js/editor/snippets.options';
import weUtils from '@web_editor/js/common/utils';
import {SIZES, MEDIAS_BREAKPOINTS} from '@web/core/ui/ui_service';
options.registry.StepsConnector = options.Class.extend({
/**
@@ -80,9 +79,7 @@ options.registry.StepsConnector = options.Class.extend({
// We don't use the service_context_get intentionally because the
// connectors are hidden as soon as the page is smaller than 992px
// (the BS lg breakpoint).
const mobileViewThreshold = MEDIAS_BREAKPOINTS[SIZES.LG].minWidth;
const isMobileView = this.$target[0].ownerDocument.documentElement.clientWidth <
mobileViewThreshold;
const isMobileView = weUtils.isMobileView(this.$target[0]);
return !isMobileView && this._super(...arguments);
},
/**