1
0
Fork 0
mirror of https://gitlab.com/bramw/baserow.git synced 2025-04-11 07:51:20 +00:00

fixed drifting context

This commit is contained in:
Bram Wiepjes 2020-12-06 18:50:25 +01:00
parent b3190723cf
commit c0590ef6b0
3 changed files with 42 additions and 9 deletions
changelog.md
web-frontend/modules/core
assets/scss
components

View file

@ -5,6 +5,7 @@
* Fixed bug where the arrow navigation didn't work for the dropdown component in
combination with a search query.
* Fixed bug where the page refreshes if you press enter in an input in the row modal.
* Fixed drifting context menu.
## Released (2020-12-01)

View file

@ -57,6 +57,12 @@
cursor: col-resize;
}
// This selector can only be used to temporarily show an element for calculating
// positions.
.forced-block {
display: block !important;
}
@keyframes spin {
0% {
transform: rotate(0);

View file

@ -63,17 +63,20 @@ export default {
*/
show(target, vertical, horizontal, offset) {
const isElementOrigin = isDomElement(target)
const updatePosition = () => {
const css = isElementOrigin
? this.calculatePositionElement(target, vertical, horizontal, offset)
: this.calculatePositionFixed(target, vertical, horizontal, offset)
const css = isElementOrigin
? this.calculatePositionElement(target, vertical, horizontal, offset)
: this.calculatePositionFixed(target, vertical, horizontal, offset)
// Set the calculated positions of the context.
for (const key in css) {
const value = css[key] !== null ? Math.ceil(css[key]) + 'px' : 'auto'
this.$el.style[key] = value
// Set the calculated positions of the context.
for (const key in css) {
const value = css[key] !== null ? Math.ceil(css[key]) + 'px' : 'auto'
this.$el.style[key] = value
}
}
updatePosition()
// If we store the element who opened the context menu we can exclude the element
// when clicked outside of this element.
this.opener = isElementOrigin ? target : null
@ -101,6 +104,12 @@ export default {
}
}
document.body.addEventListener('click', this.$el.clickOutsideEvent)
this.$el.updatePositionEvent = (event) => {
updatePosition()
}
window.addEventListener('scroll', this.$el.updatePositionEvent, true)
window.addEventListener('resize', this.$el.updatePositionEvent)
},
/**
* Hide the context menu and make sure the body event is removed.
@ -114,16 +123,33 @@ export default {
}
document.body.removeEventListener('click', this.$el.clickOutsideEvent)
window.removeEventListener('scroll', this.$el.updatePositionEvent, true)
window.removeEventListener('resize', this.$el.updatePositionEvent)
},
/**
* Calculates the absolute position of the context based on the original clicked
* element.
* element. If the target element is not visible, it might mean that we can't
* figure out the correct position, so in that case we force the element to be
* visible.
*/
calculatePositionElement(target, vertical, horizontal, offset) {
const visible =
window.getComputedStyle(target).getPropertyValue('display') !== 'none'
// If the target is not visible then we can't calculate the position, so we
// temporarily need to show the element forcefully.
if (!visible) {
target.classList.add('forced-block')
}
const targetRect = target.getBoundingClientRect()
const contextRect = this.$el.getBoundingClientRect()
const positions = { top: null, right: null, bottom: null, left: null }
if (!visible) {
target.classList.remove('forced-block')
}
// Calculate if top, bottom, left and right positions are possible.
const canTop = targetRect.top - contextRect.height - offset > 0
const canBottom =