This commit is contained in:
Yuri Kuznetsov
2024-02-18 15:33:07 +02:00
parent 7f51b3a31e
commit 88c9fbd153
2 changed files with 158 additions and 94 deletions
@@ -0,0 +1,149 @@
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM Open Source CRM application.
* Copyright (C) 2014-2024 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
import $ from 'jquery';
/**
* @internal
*/
class StickyBarHelper {
/**
* @param {import('views/record/detail').default} view
* @param {boolean} stickButtonsFormBottomSelector
* @param {boolean} stickButtonsContainerAllTheWay
* @param {number} numId
*/
constructor(view, stickButtonsFormBottomSelector, stickButtonsContainerAllTheWay, numId) {
this.view = view;
this.stickButtonsFormBottomSelector = stickButtonsFormBottomSelector;
this.stickButtonsContainerAllTheWay = stickButtonsContainerAllTheWay;
this.numId = numId;
this.themeManager = view.getThemeManager();
this.$el = view.$el;
}
init() {
const $containers = this.$el.find('.detail-button-container');
const $container = this.$el.find('.detail-button-container.record-buttons');
if (!$container.length) {
return;
}
const navbarHeight = this.themeManager.getParam('navbarHeight');
const screenWidthXs = this.themeManager.getParam('screenWidthXs');
const isSmallScreen = $(window.document).width() < screenWidthXs;
const getOffsetTop = (/** JQuery */$element) => {
let element = /** @type {HTMLElement} */$element.get(0);
let value = 0;
while (element) {
value += !isNaN(element.offsetTop) ? element.offsetTop : 0;
element = element.offsetParent;
}
if (isSmallScreen) {
return value;
}
return value - navbarHeight;
};
let stickTop = getOffsetTop($container);
const blockHeight = $container.outerHeight();
stickTop -= 5; // padding;
const $block = $('<div>')
.css('height', blockHeight + 'px')
.html('&nbsp;')
.hide()
.insertAfter($container);
let $middle = this.view.getMiddleView().$el;
const $window = $(window);
const $navbarRight = $('#navbar .navbar-right');
if (this.stickButtonsFormBottomSelector) {
const $bottom = this.$el.find(this.stickButtonsFormBottomSelector);
if ($bottom.length) {
$middle = $bottom;
}
}
$window.off('scroll.detail-' + this.numId);
$window.on('scroll.detail-' + this.numId, () => {
const edge = $middle.position().top + $middle.outerHeight(false) - blockHeight;
const scrollTop = $window.scrollTop();
if (scrollTop >= edge && !this.stickButtonsContainerAllTheWay) {
$containers.hide();
$navbarRight.removeClass('has-sticked-bar');
$block.show();
return;
}
if (isSmallScreen && $('#navbar .navbar-body').hasClass('in')) {
return;
}
if (scrollTop > stickTop) {
if (!$containers.hasClass('stick-sub')) {
$containers.addClass('stick-sub');
$block.show();
}
$navbarRight.addClass('has-sticked-bar');
$containers.show();
return;
}
if ($containers.hasClass('stick-sub')) {
$containers.removeClass('stick-sub');
$navbarRight.removeClass('has-sticked-bar');
$block.hide();
}
$containers.show();
});
}
}
export default StickyBarHelper;
+9 -94
View File
@@ -31,6 +31,7 @@
import BaseRecordView from 'views/record/base';
import ViewRecordHelper from 'view-record-helper';
import ActionItemSetup from 'helpers/action-item-setup';
import StickyBarHelper from 'helpers/record/misc/sticky-bar';
/**
* A detail record view.
@@ -1419,102 +1420,16 @@ class DetailRecordView extends BaseRecordView {
}
}
/**
* @private
*/
/** @private */
initStickableButtonsContainer() {
const $containers = this.$el.find('.detail-button-container');
const $container = this.$el.find('.detail-button-container.record-buttons');
const helper = new StickyBarHelper(
this,
this.stickButtonsFormBottomSelector,
this.stickButtonsContainerAllTheWay,
this.numId
);
if (!$container.length) {
return;
}
const navbarHeight = this.getThemeManager().getParam('navbarHeight');
const screenWidthXs = this.getThemeManager().getParam('screenWidthXs');
const isSmallScreen = $(window.document).width() < screenWidthXs;
const getOffsetTop = (/** JQuery */$element) => {
let element = /** @type {HTMLElement} */$element.get(0);
let value = 0;
while (element) {
value += !isNaN(element.offsetTop) ? element.offsetTop : 0;
element = element.offsetParent;
}
if (isSmallScreen) {
return value;
}
return value - navbarHeight;
};
let stickTop = getOffsetTop($container);
const blockHeight = $container.outerHeight();
stickTop -= 5; // padding;
const $block = $('<div>')
.css('height', blockHeight + 'px')
.html('&nbsp;')
.hide()
.insertAfter($container);
let $middle = this.getMiddleView().$el;
const $window = $(window);
const $navbarRight = $('#navbar .navbar-right');
if (this.stickButtonsFormBottomSelector) {
const $bottom = this.$el.find(this.stickButtonsFormBottomSelector);
if ($bottom.length) {
$middle = $bottom;
}
}
$window.off('scroll.detail-' + this.numId);
$window.on('scroll.detail-' + this.numId, () => {
const edge = $middle.position().top + $middle.outerHeight(false) - blockHeight;
const scrollTop = $window.scrollTop();
if (scrollTop >= edge && !this.stickButtonsContainerAllTheWay) {
$containers.hide();
$navbarRight.removeClass('has-sticked-bar');
$block.show();
return;
}
if (isSmallScreen && $('#navbar .navbar-body').hasClass('in')) {
return;
}
if (scrollTop > stickTop) {
if (!$containers.hasClass('stick-sub')) {
$containers.addClass('stick-sub');
$block.show();
}
$navbarRight.addClass('has-sticked-bar');
$containers.show();
return;
}
if ($containers.hasClass('stick-sub')) {
$containers.removeClass('stick-sub');
$navbarRight.removeClass('has-sticked-bar');
$block.hide();
}
$containers.show();
});
helper.init();
}
fetch() {