[IMP] website, *: add and review header visibility options
*: portal Adding a choice of several header behaviors (fixed, fade out with scroll, etc.). Review the way those animations works in mobile/desktop and now perform them without duplicating the header DOM element. Also allow to hide of adapt the size of the logo when the page is scrolled. Part of https://github.com/odoo/odoo/pull/38950 task-2087641 Co-authored-by: qsm-odoo <qsm@odoo.com>
This commit is contained in:
committed by
qsm-odoo
co-authored by
qsm-odoo
parent
5ba817c453
commit
3defe35a0e
@@ -5,6 +5,7 @@
|
||||
|
||||
// ====== Variables =========
|
||||
$o-theme-navbar-logo-height: $nav-link-height !default;
|
||||
$o-theme-navbar-fixed-logo-height: $nav-link-height !default;
|
||||
|
||||
// Portal toolbar (filters, search bar)
|
||||
$o-portal-mobile-toolbar: true; // Enable/Disable custom design
|
||||
@@ -47,7 +48,6 @@ header {
|
||||
height: $o-theme-navbar-logo-height;
|
||||
|
||||
@include media-breakpoint-down(sm) {
|
||||
height: auto;
|
||||
max-height: min($o-theme-navbar-logo-height, 5rem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,66 +1,66 @@
|
||||
odoo.define('website.content.menu', function (require) {
|
||||
'use strict';
|
||||
|
||||
const config = require('web.config');
|
||||
var dom = require('web.dom');
|
||||
var publicWidget = require('web.public.widget');
|
||||
var wUtils = require('website.utils');
|
||||
var animations = require('website.content.snippets.animation');
|
||||
|
||||
publicWidget.registry.affixMenu = publicWidget.Widget.extend({
|
||||
selector: 'header.o_affix_enabled',
|
||||
const BaseAnimatedHeader = animations.Animation.extend({
|
||||
disabledInEditableMode: false,
|
||||
effects: [{
|
||||
startEvents: 'scroll',
|
||||
update: '_updateHeaderOnScroll',
|
||||
}, {
|
||||
startEvents: 'resize',
|
||||
update: '_updateHeaderOnResize',
|
||||
}],
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
init: function () {
|
||||
this._super(...arguments);
|
||||
this.fixedHeader = false;
|
||||
this.scrolledPoint = 0;
|
||||
this.hasScrolled = false;
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
var def = this._super.apply(this, arguments);
|
||||
this.$main = this.$el.next('main');
|
||||
this.isOverlayHeader = !!this.$el.closest('.o_header_overlay, .o_header_overlay_theme').length;
|
||||
this.$dropdowns = this.$el.find('.dropdown, .dropdown-menu');
|
||||
this.$navbarCollapses = this.$el.find('.navbar-collapse');
|
||||
|
||||
var self = this;
|
||||
this.$headerClone = this.$target.clone().addClass('o_header_affix affix o_top_fixed_element').removeClass('o_affix_enabled').removeAttr('id');
|
||||
this.$headerClone.insertAfter(this.$target);
|
||||
this.$headers = this.$target.add(this.$headerClone);
|
||||
this.$dropdowns = this.$headers.find('.dropdown');
|
||||
this.$dropdownMenus = this.$headers.find('.dropdown-menu');
|
||||
this.$navbarCollapses = this.$headers.find('.navbar-collapse');
|
||||
|
||||
this._adaptDefaultOffset();
|
||||
wUtils.onceAllImagesLoaded(this.$headerClone).then(function () {
|
||||
self._adaptDefaultOffset();
|
||||
});
|
||||
|
||||
// Handle events for the collapse menus
|
||||
_.each(this.$headerClone.find('[data-toggle="collapse"]'), function (el) {
|
||||
var $source = $(el);
|
||||
var targetIDSelector = $source.attr('data-target');
|
||||
var $target = self.$headerClone.find(targetIDSelector);
|
||||
$source.attr('data-target', targetIDSelector + '_clone');
|
||||
$target.attr('id', targetIDSelector.substr(1) + '_clone');
|
||||
});
|
||||
// While scrolling through navbar menus, body should not be scrolled with it
|
||||
this.$headerClone.find('div.navbar-collapse').on('show.bs.collapse', function () {
|
||||
$(document.body).addClass('overflow-hidden');
|
||||
}).on('hide.bs.collapse', function () {
|
||||
// While scrolling through navbar menus on medium devices, body should not be scrolled with it
|
||||
this.$navbarCollapses.on('show.bs.collapse.BaseAnimatedHeader', function () {
|
||||
if (config.device.size_class <= config.device.SIZES.SM) {
|
||||
$(document.body).addClass('overflow-hidden');
|
||||
}
|
||||
}).on('hide.bs.collapse.BaseAnimatedHeader', function () {
|
||||
$(document.body).removeClass('overflow-hidden');
|
||||
});
|
||||
|
||||
// Window Handlers
|
||||
$(window).on('resize.affixMenu scroll.affixMenu', _.throttle(this._onWindowUpdate.bind(this), 200));
|
||||
setTimeout(this._onWindowUpdate.bind(this), 0); // setTimeout to allow override with advanced stuff... see themes
|
||||
// We can rely on transitionend which is well supported but not on
|
||||
// transitionstart, so we listen to a custom odoo event.
|
||||
this._transitionCount = 0;
|
||||
this.$el.on('odoo-transitionstart.BaseAnimatedHeader', () => this._updateMainPaddingTopLoop(1));
|
||||
this.$el.on('transitionend.BaseAnimatedHeader', () => this._updateMainPaddingTopLoop(-1));
|
||||
|
||||
return def.then(function () {
|
||||
self.trigger_up('widgets_start_request', {
|
||||
$target: self.$headerClone,
|
||||
});
|
||||
});
|
||||
return this._super(...arguments);
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
destroy: function () {
|
||||
if (this.$headerClone) {
|
||||
this.$headerClone.remove();
|
||||
$(window).off('.affixMenu');
|
||||
}
|
||||
this._super.apply(this, arguments);
|
||||
this._toggleFixedHeader(false);
|
||||
this.$el.removeClass('o_header_affixed o_header_is_scrolled o_header_no_transition');
|
||||
this.$navbarCollapses.off('.BaseAnimatedHeader');
|
||||
this.$el.off('.BaseAnimatedHeader');
|
||||
this._super(...arguments);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -69,16 +69,41 @@ publicWidget.registry.affixMenu = publicWidget.Widget.extend({
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {boolean} [useFixed=true]
|
||||
*/
|
||||
_adaptDefaultOffset: function () {
|
||||
var bottom = this.$target.offset().top + this._getHeaderHeight();
|
||||
this.$headerClone.css('margin-top', Math.min(-200, -bottom) + 'px');
|
||||
_toggleFixedHeader: function (useFixed = true) {
|
||||
this.fixedHeader = useFixed;
|
||||
this.el.classList.toggle('o_header_affixed', useFixed);
|
||||
this._updateMainPaddingTop();
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_getHeaderHeight: function () {
|
||||
return this.$headerClone.outerHeight();
|
||||
_updateMainPaddingTop: function () {
|
||||
this.headerHeight = this.$el.outerHeight();
|
||||
if (this.isOverlayHeader) {
|
||||
return;
|
||||
}
|
||||
const headerSize = this.el.classList.contains('o_header_affixed');
|
||||
this.$main.css('padding-top', headerSize ? this.headerHeight : '');
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {integer} [addCount=0]
|
||||
*/
|
||||
_updateMainPaddingTopLoop: function (addCount = 0) {
|
||||
this._updateMainPaddingTop();
|
||||
|
||||
this._transitionCount += addCount;
|
||||
this._transitionCount = Math.max(0, this._transitionCount);
|
||||
|
||||
// The normal case would be to have the transitionend event to be
|
||||
// fired but we cannot rely on it, so we use a timeout as fallback.
|
||||
clearTimeout(this._paddingLoopTimer);
|
||||
if (this._transitionCount > 0) {
|
||||
window.requestAnimationFrame(() => this._updateMainPaddingTopLoop());
|
||||
this._paddingLoopTimer = setTimeout(() => this._updateMainPaddingTopLoop(-1), 500);
|
||||
}
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -86,31 +111,232 @@ publicWidget.registry.affixMenu = publicWidget.Widget.extend({
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Called when the window is resized or scrolled -> updates affix status and
|
||||
* automatically closes submenus.
|
||||
* Called when the window is scrolled
|
||||
*
|
||||
* @private
|
||||
* @param {integer} scroll
|
||||
*/
|
||||
_onWindowUpdate: function () {
|
||||
_updateHeaderOnScroll: function (scroll) {
|
||||
// Disable css transition if refresh with scrollTop > 0
|
||||
if (!this.hasScrolled) {
|
||||
this.hasScrolled = true;
|
||||
if (scroll > 0) {
|
||||
this.$el.addClass('o_header_no_transition');
|
||||
}
|
||||
} else {
|
||||
this.$el.removeClass('o_header_no_transition');
|
||||
}
|
||||
|
||||
// Indicates the page is scrolled, the logo size is changed.
|
||||
const headerIsScrolled = (scroll > this.scrolledPoint);
|
||||
if (this.headerIsScrolled !== headerIsScrolled) {
|
||||
this.el.classList.toggle('o_header_is_scrolled', headerIsScrolled);
|
||||
this.$el.trigger('odoo-transitionstart');
|
||||
this.headerIsScrolled = headerIsScrolled;
|
||||
}
|
||||
|
||||
// Reset opened menus
|
||||
if (this.$navbarCollapses.hasClass('show')) {
|
||||
return;
|
||||
}
|
||||
|
||||
var wOffset = $(window).scrollTop();
|
||||
var hOffset = this.$target.scrollTop();
|
||||
this.$headerClone.toggleClass('affixed', wOffset > (hOffset + 300));
|
||||
|
||||
// Reset opened menus
|
||||
this.$dropdowns.add(this.$dropdownMenus).removeClass('show');
|
||||
this.$dropdowns.removeClass('show');
|
||||
this.$navbarCollapses.removeClass('show').attr('aria-expanded', false);
|
||||
},
|
||||
/**
|
||||
* Called when the window is resized
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_updateHeaderOnResize: function () {
|
||||
if (document.body.classList.contains('overflow-hidden')
|
||||
&& config.device.size_class > config.device.SIZES.SM) {
|
||||
document.body.classList.remove('overflow-hidden');
|
||||
this.$el.find('.navbar-collapse').removeClass('show');
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
publicWidget.registry.StandardAffixedHeader = BaseAnimatedHeader.extend({
|
||||
selector: 'header.o_header_standard:not(.o_header_sidebar)',
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
init: function () {
|
||||
this._super(...arguments);
|
||||
this.fixedHeaderShow = false;
|
||||
this.scrolledPoint = 300;
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
this.headerHeight = this.$el.outerHeight();
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Called when the window is scrolled
|
||||
*
|
||||
* @private
|
||||
* @param {integer} scroll
|
||||
*/
|
||||
_updateHeaderOnScroll: function (scroll) {
|
||||
this._super(...arguments);
|
||||
|
||||
const mainPosScrolled = (scroll > this.headerHeight);
|
||||
const reachPosScrolled = (scroll > this.scrolledPoint);
|
||||
|
||||
// Switch between static/fixed position of the header
|
||||
if (this.fixedHeader !== mainPosScrolled) {
|
||||
this.$el.css('transform', mainPosScrolled ? 'translate(0, -100%)' : '');
|
||||
void this.$el[0].offsetWidth; // Force a paint refresh
|
||||
this._toggleFixedHeader(mainPosScrolled);
|
||||
}
|
||||
// Show/hide header
|
||||
if (this.fixedHeaderShow !== reachPosScrolled) {
|
||||
this.$el.css('transform', reachPosScrolled ? '' : 'translate(0, -100%)');
|
||||
this.fixedHeaderShow = reachPosScrolled;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
publicWidget.registry.FixedHeader = BaseAnimatedHeader.extend({
|
||||
selector: 'header.o_header_fixed',
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
_updateHeaderOnScroll: function (scroll) {
|
||||
this._super(...arguments);
|
||||
// Need to be 'unfixed' when the window is not scrolled so that the
|
||||
// transparent menu option still works.
|
||||
if (scroll > this.scrolledPoint) {
|
||||
if (!this.$el.hasClass('o_header_affixed')) {
|
||||
this._toggleFixedHeader(true);
|
||||
}
|
||||
} else {
|
||||
this._toggleFixedHeader(false);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const BaseDisappearingHeader = publicWidget.registry.FixedHeader.extend({
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
init: function () {
|
||||
this._super(...arguments);
|
||||
this.scrollingDownwards = true;
|
||||
this.hiddenHeader = false;
|
||||
this.position = 0;
|
||||
this.checkPoint = 0;
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
destroy: function () {
|
||||
this._showHeader();
|
||||
this._super.apply(this, arguments);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
*/
|
||||
_hideHeader: function () {},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_showHeader: function () {},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
_updateHeaderOnScroll: function (scroll) {
|
||||
this._super(...arguments);
|
||||
|
||||
const scrollingDownwards = (scroll > this.position);
|
||||
if (scrollingDownwards !== this.scrollingDownwards) {
|
||||
this.checkPoint = scroll;
|
||||
}
|
||||
|
||||
if (scrollingDownwards) {
|
||||
if (!this.hiddenHeader && scroll - this.checkPoint > 200) {
|
||||
this.hiddenHeader = true;
|
||||
this._hideHeader();
|
||||
}
|
||||
} else {
|
||||
if (this.hiddenHeader && scroll - this.checkPoint < -100) {
|
||||
this.hiddenHeader = false;
|
||||
this._showHeader();
|
||||
}
|
||||
}
|
||||
|
||||
this.scrollingDownwards = scrollingDownwards;
|
||||
this.position = scroll;
|
||||
},
|
||||
});
|
||||
|
||||
publicWidget.registry.DisappearingHeader = BaseDisappearingHeader.extend({
|
||||
selector: 'header.o_header_disappears',
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
_hideHeader: function () {
|
||||
this.$el.css('transform', 'translate(0, -100%)');
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
_showHeader: function () {
|
||||
this.$el.css('transform', '');
|
||||
},
|
||||
});
|
||||
|
||||
publicWidget.registry.FadeOutHeader = BaseDisappearingHeader.extend({
|
||||
selector: 'header.o_header_fade_out',
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
_hideHeader: function () {
|
||||
this.$el.stop(false, true).fadeOut();
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
_showHeader: function () {
|
||||
this.$el.stop(false, true).fadeIn();
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Auto adapt the header layout so that elements are not wrapped on a new line.
|
||||
*
|
||||
* Note: this works well with the affixMenu... by chance (autohideMenu is called
|
||||
* after alphabetically).
|
||||
*/
|
||||
publicWidget.registry.autohideMenu = publicWidget.Widget.extend({
|
||||
selector: 'header #top_menu',
|
||||
@@ -225,7 +451,7 @@ publicWidget.registry.menuDirection = publicWidget.Widget.extend({
|
||||
// If can't open in the current direction because it would overflow the
|
||||
// window, change the direction. But if the other direction would do the
|
||||
// same, change back the direction.
|
||||
for (var i = 0 ; i < 2 ; i++) {
|
||||
for (var i = 0; i < 2; i++) {
|
||||
if (!this._checkOpening(alignment, liOffset, liWidth, menuWidth, windowWidth)) {
|
||||
alignment = (alignment === 'left' ? 'right' : 'left');
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ $-with-support-theme-fonts: ();
|
||||
$o-theme-fonts: $-with-support-theme-fonts;
|
||||
|
||||
$o-theme-navbar-logo-height: o-website-value('logo-height') !default;
|
||||
$o-theme-navbar-fixed-logo-height: o-website-value('fixed-logo-height') !default;
|
||||
$o-theme-font: nth($o-theme-fonts, o-website-value('font-number')) !default;
|
||||
$o-theme-headings-font: nth($o-theme-fonts, o-website-value('headings-font-number')) !default;
|
||||
$o-theme-navbar-font: nth($o-theme-fonts, o-website-value('navbar-font-number')) !default;
|
||||
|
||||
@@ -161,3 +161,10 @@ table.editorbar-panel {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.editor_has_snippets {
|
||||
.o_header_affixed {
|
||||
left: $o-we-sidebar-width !important;
|
||||
top: var(--o-we-toolbar-height) !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ $-font-numbers: (
|
||||
--h6: #{$-h6-color};
|
||||
|
||||
--logo-height: #{$o-theme-navbar-logo-height};
|
||||
--fixed-logo-height: #{$o-theme-navbar-fixed-logo-height};
|
||||
--number-of-fonts: #{length($o-theme-fonts)};
|
||||
}
|
||||
|
||||
@@ -643,28 +644,50 @@ table.table_desc tr td {
|
||||
// Layout
|
||||
//
|
||||
|
||||
// Header
|
||||
.o_header_affix {
|
||||
$-transition-duration: 200ms;
|
||||
|
||||
// Affixed Header
|
||||
.o_header_affixed {
|
||||
display: block;
|
||||
@include o-position-absolute(0, 0, auto, 0);
|
||||
position: fixed;
|
||||
z-index: $zindex-modal - 20;
|
||||
background: $light;
|
||||
margin-top: -999px;
|
||||
transition: margin-top 500ms ease 0s;
|
||||
@include media-breakpoint-down(sm) {
|
||||
.navbar-collapse {
|
||||
@if o-website-value('header-template') != 'logo_hamburger' {
|
||||
max-height: 70vh;
|
||||
}
|
||||
|
||||
&:not(.o_header_no_transition) {
|
||||
transition: transform $-transition-duration;
|
||||
}
|
||||
|
||||
.navbar-collapse {
|
||||
@if o-website-value('header-template') != 'logo_hamburger' {
|
||||
max-height: 70vh;
|
||||
}
|
||||
&.show {
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
&.affixed {
|
||||
margin-top: 0px !important; // the default margin-top is adapted in JS
|
||||
&.o_header_is_scrolled {
|
||||
.navbar-brand {
|
||||
font-size: $o-theme-navbar-fixed-logo-height / $line-height-base;
|
||||
|
||||
img {
|
||||
height: $o-theme-navbar-fixed-logo-height;
|
||||
}
|
||||
}
|
||||
@include media-breakpoint-up(md) {
|
||||
@if (index(('menu_logo_below', 'logo_menu_below'), o-website-value('header-template'))) != null {
|
||||
.navbar-brand {
|
||||
font-size: 0px;
|
||||
opacity: 0;
|
||||
img {
|
||||
height: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#oe_main_menu_navbar + #wrapwrap .o_header_affix {
|
||||
#oe_main_menu_navbar + #wrapwrap .o_header_affixed {
|
||||
top: $o-navbar-height;
|
||||
}
|
||||
|
||||
@@ -694,6 +717,17 @@ table.table_desc tr td {
|
||||
|
||||
// Header templates
|
||||
header {
|
||||
&:not(.o_header_no_transition) {
|
||||
.navbar-brand {
|
||||
transition: font-size $-transition-duration, opacity $-transition-duration ease-out;
|
||||
|
||||
img {
|
||||
transition: height $-transition-duration;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
z-index: 1;
|
||||
@include media-breakpoint-up(md) {
|
||||
// Allow to center the logo, ignoring the toggler space
|
||||
.o_navbar_toggler_container {
|
||||
@@ -715,14 +749,20 @@ header {
|
||||
.o_navbar_toggler_container {
|
||||
direction: rtl;
|
||||
}
|
||||
.container {
|
||||
&:not(.o_header_is_scrolled) .container {
|
||||
padding-top: $spacer;
|
||||
padding-bottom: $spacer;
|
||||
}
|
||||
.container {
|
||||
transition: padding 200ms;
|
||||
|
||||
#top_menu.navbar-nav {
|
||||
height: 90vh;
|
||||
padding-top : 10vh;
|
||||
}
|
||||
.dropdown-menu {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
} @else if index(('logo_menu_below', 'menu_logo_below'), o-website-value('header-template')) {
|
||||
@@ -741,10 +781,12 @@ header {
|
||||
margin: auto;
|
||||
}
|
||||
.navbar-brand {
|
||||
@if o-website-value('header-template') == 'menu_logo_below' {
|
||||
margin-top: $navbar-padding-y;
|
||||
} @else {
|
||||
margin-bottom: $navbar-padding-y;
|
||||
@include media-breakpoint-up(md) {
|
||||
@if o-website-value('header-template') == 'menu_logo_below' {
|
||||
margin-top: $navbar-padding-y;
|
||||
} @else {
|
||||
margin-bottom: $navbar-padding-y;
|
||||
}
|
||||
}
|
||||
}
|
||||
@if o-website-value('header-template') == 'menu_logo_below' {
|
||||
@@ -788,7 +830,7 @@ header {
|
||||
}
|
||||
|
||||
#wrapwrap.o_header_overlay {
|
||||
> header:not(.o_header_affix) {
|
||||
> header:not(.o_header_affixed) {
|
||||
@include o-position-absolute(0, 0, auto, 0);
|
||||
z-index: 1000;
|
||||
|
||||
|
||||
@@ -389,13 +389,23 @@
|
||||
data-no-check="true"
|
||||
groups="website.group_website_designer">
|
||||
<we-checkbox string="Show Sign In" data-customize-website-views="portal.portal_show_sign_in" data-reload="/"/>
|
||||
<we-checkbox string="Fixed Top Menu" data-customize-website-views="website.affix_top_menu" data-reload="/"/>
|
||||
<we-colorpicker string="Background Color" data-customize-website-color="" data-color="menu"/>
|
||||
<we-select string="Logo" data-reload="/">
|
||||
<we-button data-customize-website-views="website.website_name">Text</we-button>
|
||||
<we-button data-customize-website-views="website.layout_logo_show">Image</we-button>
|
||||
</we-select>
|
||||
<we-input string="Logo Height" data-customize-website-variable="null" data-variable="logo-height" data-unit="px" data-save-unit="rem"/>
|
||||
<we-input string="Logo Height"
|
||||
data-customize-website-variable="null"
|
||||
data-variable="logo-height"
|
||||
data-unit="px"
|
||||
data-save-unit="rem"/>
|
||||
<we-input id="option_logo_height_scrolled"
|
||||
string="Logo Height (Scrolled)"
|
||||
data-customize-website-variable="null"
|
||||
data-variable="fixed-logo-height"
|
||||
data-unit="px"
|
||||
data-save-unit="rem"
|
||||
data-dependencies="!header_visibility_scroll_opt"/>
|
||||
<we-row string="Font">
|
||||
<we-fontfamilypicker data-variable="navbar-font-number"/>
|
||||
<we-input data-customize-website-variable="null" data-variable="header-font-size" data-unit="px" data-save-unit="rem"/>
|
||||
@@ -427,18 +437,50 @@
|
||||
data-customize-website-variable="logo_hamburger"
|
||||
string="Logo - Hamburger (cover)"/>
|
||||
</we-select>
|
||||
<we-select id="header_visibilities_list" string="Header Visibility">
|
||||
<we-button id="option_header_visibility_standard"
|
||||
data-name="header_visibility_standard_opt"
|
||||
data-select-class="o_header_standard"
|
||||
data-customize-website-views="website.header_visibility_standard"
|
||||
string="Standard"/>
|
||||
<we-button id="option_header_visibility_scroll"
|
||||
data-name="header_visibility_scroll_opt"
|
||||
data-select-class=""
|
||||
data-customize-website-views=""
|
||||
string="Scroll"/>
|
||||
<we-button id="option_header_visibility_fixed"
|
||||
data-name="header_visibility_fixed_opt"
|
||||
data-select-class="o_header_fixed"
|
||||
data-customize-website-views="website.header_visibility_fixed"
|
||||
string="Fixed"/>
|
||||
<we-button id="option_header_visibility_disappears"
|
||||
data-name="header_visibility_disappears_opt"
|
||||
data-select-class="o_header_disappears"
|
||||
data-customize-website-views="website.header_visibility_disappears"
|
||||
string="Disappears"/>
|
||||
<we-button id="option_header_visibility_fade_out"
|
||||
data-name="header_visibility_fade_out_opt"
|
||||
data-select-class="o_header_fade_out"
|
||||
data-customize-website-views="website.header_visibility_fade_out"
|
||||
string="Fade Out"/>
|
||||
</we-select>
|
||||
</div>
|
||||
|
||||
<div data-js="topMenuTransparency"
|
||||
data-selector="[data-main-object^='website.page('] #wrapwrap > header"
|
||||
data-no-check="true">
|
||||
<we-checkbox string="Transparent on this page" data-transparent="true" data-no-preview="true"/>
|
||||
<we-checkbox id="option_header_transparent"
|
||||
string="Transparent on this page"
|
||||
data-name="header_transparent_opt"
|
||||
data-transparent="true"
|
||||
data-no-preview="true"/>
|
||||
</div>
|
||||
|
||||
<div data-js="topMenuColor"
|
||||
data-selector="[data-main-object^='website.page('] #wrapwrap > header"
|
||||
data-no-check="true">
|
||||
<we-colorpicker string="Transparent color"
|
||||
id="option_header_transparent_color"
|
||||
data-select-style="true"
|
||||
data-css-property="background-color"
|
||||
data-color-prefix="bg-"
|
||||
|
||||
@@ -244,9 +244,27 @@
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="affix_top_menu" inherit_id="website.layout" name="Fixed Top Menu">
|
||||
<template id="header_visibility_standard" inherit_id="website.layout" name="Header Visibility Standard">
|
||||
<xpath expr="//header" position="attributes">
|
||||
<attribute name="t-attf-class" add="#{'o_affix_enabled'}" separator=" "/>
|
||||
<attribute name="t-attf-class" add="o_header_standard o_top_fixed_element" separator=" "/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="header_visibility_fixed" inherit_id="website.layout" name="Header Visibility Fixed" active="False">
|
||||
<xpath expr="//header" position="attributes">
|
||||
<attribute name="t-attf-class" add="o_header_fixed o_top_fixed_element" separator=" "/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="header_visibility_disappears" inherit_id="website.layout" name="Header Visibility Disappears" active="False">
|
||||
<xpath expr="//header" position="attributes">
|
||||
<attribute name="t-attf-class" add="o_header_disappears o_top_fixed_element" separator=" "/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="header_visibility_fade_out" inherit_id="website.layout" name="Header Visibility Fade Out" active="False">
|
||||
<xpath expr="//header" position="attributes">
|
||||
<attribute name="t-attf-class" add="o_header_fade_out o_top_fixed_element" separator=" "/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ publicWidget.registry.productsRecentlyViewedSnippet = publicWidget.Widget.extend
|
||||
},
|
||||
}).then(function (data) {
|
||||
wSaleUtils.updateCartNavBar(data);
|
||||
var $navButton = wSaleUtils.getNavBarButton('.o_wsale_my_cart');
|
||||
var $navButton = $('header .o_wsale_my_cart').first();
|
||||
var fetch = self._fetch();
|
||||
var animation = wSaleUtils.animateClone($navButton, $(ev.currentTarget).parents('.o_carousel_product_card'), 25, 40);
|
||||
Promise.all([fetch, animation]).then(function (values) {
|
||||
|
||||
@@ -1,24 +1,6 @@
|
||||
odoo.define('website_sale.utils', function (require) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Gets the element in the navbar currently displayed.
|
||||
* Depending on the scroll position, it could either be the one in the main
|
||||
* top bar or the one in the affixed navbar.
|
||||
*
|
||||
* @private
|
||||
* @param {string} selector
|
||||
* @returns {jQuery}
|
||||
*/
|
||||
function getNavBarButton(selector) {
|
||||
var $affixedHeaderButton = $('header.affixed ' + selector);
|
||||
if ($affixedHeaderButton.length) {
|
||||
return $affixedHeaderButton;
|
||||
} else {
|
||||
return $('header ' + selector).first();
|
||||
}
|
||||
}
|
||||
|
||||
function animateClone($cart, $elem, offsetTop, offsetLeft) {
|
||||
$cart.find('.o_animate_blink').addClass('o_red_highlight o_shadow_animation').delay(500).queue(function () {
|
||||
$(this).removeClass("o_shadow_animation").dequeue();
|
||||
@@ -72,7 +54,6 @@ function updateCartNavBar(data) {
|
||||
|
||||
return {
|
||||
animateClone: animateClone,
|
||||
getNavBarButton: getNavBarButton,
|
||||
updateCartNavBar: updateCartNavBar,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -105,7 +105,7 @@ publicWidget.registry.ProductWishlist = publicWidget.Widget.extend(VariantMixin,
|
||||
product_id: productId,
|
||||
},
|
||||
}).then(function () {
|
||||
var $navButton = wSaleUtils.getNavBarButton('.o_wsale_my_wish');
|
||||
var $navButton = $('header .o_wsale_my_wish').first();
|
||||
self.wishlistProductIDs.push(productId);
|
||||
self._updateWishlistView();
|
||||
wSaleUtils.animateClone($navButton, $el.closest('form'), 25, 40);
|
||||
@@ -157,7 +157,7 @@ publicWidget.registry.ProductWishlist = publicWidget.Widget.extend(VariantMixin,
|
||||
* @private
|
||||
*/
|
||||
_addOrMoveWish: function (e) {
|
||||
var $navButton = wSaleUtils.getNavBarButton('.o_wsale_my_cart');
|
||||
var $navButton = $('header .o_wsale_my_cart').first();
|
||||
var tr = $(e.currentTarget).parents('tr');
|
||||
var product = tr.data('product-id');
|
||||
$('.o_wsale_my_cart').removeClass('d-none');
|
||||
|
||||
Reference in New Issue
Block a user