mirror of
https://gitlab.com/bramw/baserow.git
synced 2024-11-21 23:37:55 +00:00
203 lines
6.4 KiB
Vue
203 lines
6.4 KiB
Vue
<template>
|
|
<div class="scrollbars">
|
|
<div
|
|
v-if="vertical !== null && verticalShow"
|
|
class="scrollbars__vertical-wrapper"
|
|
>
|
|
<div
|
|
ref="scrollbarVertical"
|
|
class="scrollbars__vertical"
|
|
:style="{ top: verticalTop + '%', height: verticalHeight + '%' }"
|
|
@mousedown="mouseDownVertical($event)"
|
|
></div>
|
|
</div>
|
|
<div
|
|
v-if="horizontal !== null && horizontalShow"
|
|
class="scrollbars__horizontal-wrapper"
|
|
>
|
|
<div
|
|
ref="scrollbarHorizontal"
|
|
class="scrollbars__horizontal"
|
|
:style="{ left: horizontalLeft + '%', width: horizontalWidth + '%' }"
|
|
@mousedown="mouseDownHorizontal($event)"
|
|
></div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { floor, ceil } from '@baserow/modules/core/utils/number'
|
|
|
|
/**
|
|
* This component will render custom scrollbars to a scrollable div. They will
|
|
* automatically adjust when you resize the window and can be dragged.
|
|
*/
|
|
export default {
|
|
name: 'Scrollbars',
|
|
props: {
|
|
/**
|
|
* The vertical property should be the reference of the vertical scrollable element
|
|
* in the parent component.
|
|
*/
|
|
vertical: {
|
|
required: false,
|
|
type: String,
|
|
default: null,
|
|
},
|
|
/**
|
|
* The horizontal property should be the reference of the vertical scrollable
|
|
* element in the parent component.
|
|
*/
|
|
horizontal: {
|
|
required: false,
|
|
type: String,
|
|
default: null,
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
dragging: null,
|
|
elementStart: 0,
|
|
mouseStart: 0,
|
|
verticalShow: false,
|
|
verticalHeight: 0,
|
|
verticalTop: 0,
|
|
horizontalShow: false,
|
|
horizontalWidth: 0,
|
|
horizontalLeft: 0,
|
|
}
|
|
},
|
|
mounted() {
|
|
this.update()
|
|
|
|
// Register the event when the window is resized because the size of the scrollbars
|
|
// might need to updated.
|
|
this.$el.resizeEventListener = () => this.update()
|
|
window.addEventListener('resize', this.$el.resizeEventListener)
|
|
|
|
// Register the mouseup event for when the user releases the mouse button. This is
|
|
// needed for the dragging of the scrollbar handle.
|
|
this.$el.mouseUpEventListener = (event) => this.mouseUp(event)
|
|
window.addEventListener('mouseup', this.$el.mouseUpEventListener)
|
|
|
|
// Register the mousemove event for when the user moves his mouse. This is needed
|
|
// for the dragging of the scrollbar handle.
|
|
this.$el.mouseMoveEventListener = (event) => this.mouseMove(event)
|
|
window.addEventListener('mousemove', this.$el.mouseMoveEventListener)
|
|
},
|
|
beforeDestroy() {
|
|
window.removeEventListener('resize', this.$el.resizeEventListener)
|
|
window.removeEventListener('mouseup', this.$el.mouseUpEventListener)
|
|
window.removeEventListener('mousemove', this.$el.mouseMoveEventListener)
|
|
},
|
|
methods: {
|
|
update() {
|
|
if (this.vertical !== null) {
|
|
this.updateVertical()
|
|
}
|
|
if (this.horizontal !== null) {
|
|
this.updateHorizontal()
|
|
}
|
|
},
|
|
/**
|
|
* Method that updates the visibility, height and top position of the vertical
|
|
* scrollbar handle based on the scrollTop of the vertical scrolling element of the
|
|
* parent.
|
|
*/
|
|
updateVertical() {
|
|
const element = this.$parent[this.vertical]()
|
|
const show = element.scrollHeight > element.clientHeight
|
|
// @TODO if the client height is very high we have a minimum of 2%, but this needs
|
|
// to be subtracted from the top position so that it fits. Same goes for the
|
|
// horizontal handler.
|
|
const height = Math.max(
|
|
floor((element.clientHeight / element.scrollHeight) * 100, 2),
|
|
2
|
|
)
|
|
const top = ceil((element.scrollTop / element.scrollHeight) * 100, 2)
|
|
|
|
this.verticalShow = show
|
|
this.verticalHeight = height
|
|
this.verticalTop = top
|
|
},
|
|
/**
|
|
* Method that updates the visibility, width and left position of the horizontal
|
|
* scrollbar handle based on the scrollLeft of horizontal scrolling element of the
|
|
* parent.
|
|
*/
|
|
updateHorizontal() {
|
|
const element = this.$parent[this.horizontal]()
|
|
const show = element.scrollWidth > element.clientWidth
|
|
const width = Math.max(
|
|
floor((element.clientWidth / element.scrollWidth) * 100, 2),
|
|
2
|
|
)
|
|
const left = ceil((element.scrollLeft / element.scrollWidth) * 100, 2)
|
|
this.horizontalShow = show
|
|
this.horizontalWidth = width
|
|
this.horizontalLeft = left
|
|
},
|
|
/**
|
|
* Event that is called when the user clicks on the vertical scrollbar handle. It
|
|
* will start the vertical dragging.
|
|
*/
|
|
mouseDownVertical(event) {
|
|
event.preventDefault()
|
|
this.dragging = 'vertical'
|
|
this.elementStart = this.$refs.scrollbarVertical.offsetTop
|
|
this.mouseStart = event.clientY
|
|
},
|
|
/**
|
|
* Event that is called when the user clicks on the horizontal scrollbar handle. It
|
|
* will start the horizontal dragging.
|
|
*/
|
|
mouseDownHorizontal(event) {
|
|
event.preventDefault()
|
|
this.dragging = 'horizontal'
|
|
this.elementStart = this.$refs.scrollbarHorizontal.offsetLeft
|
|
this.mouseStart = event.clientX
|
|
},
|
|
/**
|
|
* Event that is called when the mouse moves. If vertical of horizontal scrollbar
|
|
* handle is in a dragging state it will emit an event with the new scrollTop.
|
|
*/
|
|
mouseMove(event) {
|
|
if (this.dragging === 'vertical') {
|
|
event.preventDefault()
|
|
const element = this.$parent[this.vertical]()
|
|
const delta = event.clientY - this.mouseStart
|
|
const pixel = element.scrollHeight / element.clientHeight
|
|
const top = Math.ceil((this.elementStart + delta) * pixel)
|
|
|
|
this.$emit('vertical', top)
|
|
this.updateVertical()
|
|
}
|
|
|
|
if (this.dragging === 'horizontal') {
|
|
event.preventDefault()
|
|
const element = this.$parent[this.horizontal]()
|
|
const delta = event.clientX - this.mouseStart
|
|
const pixel = element.scrollWidth / element.clientWidth
|
|
const left = Math.ceil((this.elementStart + delta) * pixel)
|
|
|
|
this.$emit('horizontal', left)
|
|
this.updateHorizontal()
|
|
}
|
|
},
|
|
/**
|
|
* Event that is called when the mouse button is released. It will stop the dragging
|
|
* of the handle.
|
|
*/
|
|
mouseUp() {
|
|
if (this.dragging === null) {
|
|
return
|
|
}
|
|
|
|
this.dragging = null
|
|
this.elementStart = 0
|
|
this.mouseStart = 0
|
|
},
|
|
},
|
|
}
|
|
</script>
|