Skip to content

Added auto-scroll, scroll prevention (to help Vue2-Dragula on mobile), size recalculation on component updates #41

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
356 changes: 193 additions & 163 deletions src/js/components/horizontal-scrollbar.vue
Original file line number Diff line number Diff line change
@@ -1,163 +1,193 @@

<template>
<div>
<div
v-if="width < 100"
class="vue-scrollbar__scrollbar-horizontal"
ref="container"
@click="jump">

<div
:class="'scrollbar' + ( dragging || draggingFromParent ? '' : ' vue-scrollbar-transition')"
ref="scrollbar"
@touchstart="startDrag"
@mousedown="startDrag"
:style="{
width: this.width+'%',
left: this.scrolling + '%'
}" >
</div>

</div>
</div>
</template>

<script>

export default {

props: {
draggingFromParent: Boolean,
scrolling: Number,
wrapper: Object,
area: Object,
onChangePosition: Function,
onDragging: Function,
onStopDrag: Function,
},

data () {
return {
width: 0,
dragging: false,
start: 0
}
},


watch: {
'wrapper.width' (val, old) {
this.calculateSize(this)
},

'area.width' (val, old) {
this.calculateSize(this)
}
},


methods: {

startDrag (e) {

e.preventDefault()
e.stopPropagation()

e = e.changedTouches ? e.changedTouches[0] : e

// Prepare To Drag
this.dragging = true
this.start = e.clientX

},

onDrag(e){

if(this.dragging){

// Make The Parent being in the Dragging State
this.onDragging()

e.preventDefault()
e.stopPropagation()

e = e.changedTouches ? e.changedTouches[0] : e

let xMovement = e.clientX - this.start
let xMovementPercentage = xMovement / this.wrapper.width * 100;

// Update the last e.clientX
this.start = e.clientX

// The next Horizontal Value will be
let next = this.scrolling + xMovementPercentage

// Tell the parent to change the position
this.onChangePosition(next, 'horizontal')

}

},

stopDrag(e){
if(this.dragging){
// Parent Should Change the Dragging State
this.onStopDrag()
this.dragging = false
}
},

jump(e){

let isContainer = e.target === this.$refs.container

if(isContainer){

// Get the Element Position
let position = this.$refs.scrollbar.getBoundingClientRect()

// Calculate the horizontal Movement
let xMovement = e.clientX - position.left
let centerize = (this.width / 2)
let xMovementPercentage = xMovement / this.wrapper.width * 100 - centerize

// Update the last e.clientX
this.start = e.clientX

// The next Horizontal Value will be
let next = this.scrolling + xMovementPercentage

// Tell the parent to change the position
this.onChangePosition(next, 'horizontal')

}
},

calculateSize(source){
// Scrollbar Width
this.width = source.wrapper.width / source.area.width * 100
},

},

mounted () {
this.calculateSize(this)

// Put the Listener
document.addEventListener("mousemove", this.onDrag)
document.addEventListener("touchmove", this.onDrag)
document.addEventListener("mouseup", this.stopDrag)
document.addEventListener("touchend", this.stopDrag)
},

beforeDestroy () {
// Remove the Listener
document.removeEventListener("mousemove", this.onDrag)
document.removeEventListener("touchmove", this.onDrag)
document.removeEventListener("mouseup", this.stopDrag)
document.removeEventListener("touchend", this.stopDrag)
}

}

</script>

<template>
<div
v-if="width < 100"
class="vue-scrollbar__scrollbar-horizontal"
:style="reducedWidth"
ref="container"
@click="jump">

<div
:class="'scrollbar' + ( dragging || draggingFromParent ? '' : ' vue-scrollbar-transition')"
ref="scrollbar"
@touchstart="startDrag"
@mousedown="startDrag"
@mousemove="onDrag"
@touchmove="onDrag"
@mouseup="stopDrag"
@touchend="stopDrag"
:style="{
width: width+'%',
left: scrolling + '%'
}" >
</div>

</div>
</template>

<script>

export default {

props: {
draggingFromParent: {
type: Boolean,
default: false,
},
scrolling: {
type: Number,
default: 0,
},
wrapper: {
type: Object,
default: () => ({}),
},
area: {
type: Object,
default: () => ({}),
},
offset:
{
type: Number,
default: 0
},
onChangePosition: {
type: Function,
default: () => false,
},
onDragging: {
type: Function,
default: () => false,
},
onStopDrag: {
type: Function,
default: () => false,
},
},

data () {
return {
width: 0,
height: 0,
dragging: false,
start: 0
}
},

computed: {
reducedWidth() {
// vue-scrollbar.vue CSS specifies 18px for the vertical bar width and 1px for the borders
// we shrink the width of the horizontal bar so that it does not overlap with the
// vertical bar and remove the right border of the horizontal bar - but only if
// the vertical bar is currently visible
return this.height < 100
? { width: `calc(100% - ${18}px)`, borderRightWidth: 0 }
: { width: '100%' };
},
},

watch: {
'wrapper.width' (val, old) {
this.calculateSize()
if(this.scrolling + this.width > 100) this.onChangePosition(100, 'horizontal')
},

'area.width' (val, old) {
this.calculateSize()
if(this.scrolling + this.width > 100) this.onChangePosition(100, 'horizontal')
}
},


methods: {

startDrag (e) {

e.preventDefault()
e.stopPropagation()

e = e.changedTouches ? e.changedTouches[0] : e

// Prepare To Drag
this.dragging = true
this.start = e.clientX

},

onDrag(e){

if(this.dragging){

// Make The Parent being in the Dragging State
this.onDragging()

e.preventDefault()
e.stopPropagation()

e = e.changedTouches ? e.changedTouches[0] : e

const xMovement = e.clientX - this.start
const xMovementPercentage = xMovement / this.wrapper.width * 100;

// Update the last e.clientX
this.start = e.clientX

// The next Horizontal Value will be
const next = this.scrolling + xMovementPercentage

// Tell the parent to change the position
this.onChangePosition(next, 'horizontal')

}

},

stopDrag(e){
if(this.dragging){
// Parent Should Change the Dragging State
this.onStopDrag()
this.dragging = false
}
},

jump(e){

const isContainer = e.target === this.$refs.container

if(isContainer){

// Get the Element Position
const position = this.$refs.scrollbar.getBoundingClientRect()

// Calculate the horizontal Movement
const xMovement = e.clientX - position.left
const centerize = (this.width / 2)
const xMovementPercentage = xMovement / this.wrapper.width * 100 - centerize

// Update the last e.clientX
this.start = e.clientX

// The next Horizontal Value will be
const next = this.scrolling + xMovementPercentage

// Tell the parent to change the position
this.onChangePosition(next, 'horizontal')

}
},

calculateSize(){
// Scrollbar Width
this.width = this.wrapper.width / this.area.width * 100
this.height = (this.wrapper.height / this.area.height) * 100;
},

},

mounted () {
this.calculateSize()
},

}

</script>
Loading