scinote-web/app/javascript/vue/shared/mixins/fixed_flyout.js

92 lines
2.6 KiB
JavaScript
Raw Normal View History

2023-12-05 03:59:16 +08:00
export default {
data() {
return {
overflowContainerScrollTop: 0,
2023-12-12 19:17:38 +08:00
overflowContainerScrollLeft: 0
2023-12-05 03:59:16 +08:00
};
},
watch: {
isOpen() {
if (this.isOpen) {
2024-01-16 20:53:41 +08:00
this.$emit('open');
2023-12-05 03:59:16 +08:00
this.$nextTick(() => {
2024-01-12 00:42:17 +08:00
this.setPosition();
2023-12-05 03:59:16 +08:00
this.overflowContainerListener();
});
}
2024-01-12 00:42:17 +08:00
}
2023-12-05 03:59:16 +08:00
},
methods: {
overflowContainerListener() {
const { field, flyout } = this.$refs;
2024-01-12 00:42:17 +08:00
2023-12-05 03:59:16 +08:00
if (!field || !flyout) return;
2023-12-12 19:17:38 +08:00
const fieldRect = field.getBoundingClientRect();
2023-12-05 03:59:16 +08:00
if (this.overflowContainerScrollTop !== fieldRect.top) {
this.setPosition();
}
2023-12-12 19:17:38 +08:00
if (this.overflowContainerScrollLeft !== fieldRect.left) {
this.setPosition();
}
this.overflowContainerScrollLeft = fieldRect.left;
2023-12-05 03:59:16 +08:00
this.overflowContainerScrollTop = fieldRect.top;
setTimeout(() => {
this.overflowContainerListener();
}, 10);
},
setPosition() {
const { field, flyout } = this.$refs;
if (!field || !flyout) return;
const rect = field.getBoundingClientRect();
const flyoutRect = flyout.getBoundingClientRect();
2023-12-05 03:59:16 +08:00
const screenHeight = window.innerHeight;
const windowHasScroll = document.documentElement.scrollHeight > document.documentElement.clientHeight;
let rightScrollOffset = 0;
const { left, width } = rect;
const top = rect.top + rect.height;
const bottom = screenHeight - rect.bottom + rect.height;
const right = window.innerWidth - rect.right;
if (windowHasScroll) {
rightScrollOffset = 14;
}
if (this.fixedWidth) {
flyout.style.width = `${width}px`;
} else {
flyout.style.minWidth = `${width}px`;
}
if (window.innerWidth - flyoutRect.right < 0) { // when flyout is out of screen
flyout.style.left = 'unset';
flyout.style.right = `${width - Math.abs(right)}px`;
} else if (this.position === 'right') {
2023-12-05 03:59:16 +08:00
flyout.style.right = `${right - rightScrollOffset}px`;
flyout.style.left = 'unset';
2023-12-05 03:59:16 +08:00
} else {
flyout.style.left = `${left}px`;
flyout.style.right = 'unset';
2023-12-05 03:59:16 +08:00
}
2023-12-05 03:59:16 +08:00
if (bottom < top) {
flyout.style.bottom = `${bottom}px`;
flyout.style.top = 'unset';
flyout.style.boxShadow = '0px -16px 32px 0px rgba(16, 24, 40, 0.07)';
flyout.style.maxHeight = `${screenHeight - bottom - 25}px`;
2023-12-05 03:59:16 +08:00
} else {
flyout.style.top = `${top}px`;
flyout.style.bottom = 'unset';
flyout.style.boxShadow = '';
flyout.style.maxHeight = `${screenHeight - top - 25}px`;
2023-12-05 03:59:16 +08:00
}
2023-12-12 19:17:38 +08:00
}
}
2023-12-05 03:59:16 +08:00
};