mirror of
https://github.com/tenrok/vue-select.git
synced 2026-06-13 08:32:26 +03:00
feat: add autoscroll boolean prop (#1160)
* feat: add autoscroll boolean prop Fixes #449 * refactor: update autoscroll implementation Closes #1028 Closes #910 * refactor: only call maybeAdjustScroll in the watcher * docs: upgrade vuepress
This commit is contained in:
+28
-60
@@ -1,8 +1,17 @@
|
||||
export default {
|
||||
props: {
|
||||
autoscroll: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
typeAheadPointer() {
|
||||
this.maybeAdjustScroll();
|
||||
}
|
||||
if (this.autoscroll) {
|
||||
this.maybeAdjustScroll();
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
@@ -13,75 +22,34 @@ export default {
|
||||
* @returns {*}
|
||||
*/
|
||||
maybeAdjustScroll() {
|
||||
let pixelsToPointerTop = this.pixelsToPointerTop();
|
||||
let pixelsToPointerBottom = this.pixelsToPointerBottom();
|
||||
const optionEl =
|
||||
this.$refs.dropdownMenu?.children[this.typeAheadPointer] || false;
|
||||
|
||||
if (pixelsToPointerTop <= this.viewport().top) {
|
||||
return this.scrollTo(pixelsToPointerTop);
|
||||
} else if (pixelsToPointerBottom >= this.viewport().bottom) {
|
||||
return this.scrollTo(this.viewport().top + this.pointerHeight());
|
||||
}
|
||||
},
|
||||
if (optionEl) {
|
||||
const bounds = this.getDropdownViewport();
|
||||
const { top, bottom, height } = optionEl.getBoundingClientRect();
|
||||
|
||||
/**
|
||||
* The distance in pixels from the top of the dropdown
|
||||
* list to the top of the current pointer element.
|
||||
* @returns {number}
|
||||
*/
|
||||
pixelsToPointerTop() {
|
||||
let pixelsToPointerTop = 0;
|
||||
if (this.$refs.dropdownMenu && this.dropdownOpen) {
|
||||
for (let i = 0; i < this.typeAheadPointer; i++) {
|
||||
pixelsToPointerTop += this.$refs.dropdownMenu.children[i]
|
||||
.offsetHeight;
|
||||
if (top < bounds.top) {
|
||||
return (this.$refs.dropdownMenu.scrollTop = optionEl.offsetTop);
|
||||
} else if (bottom > bounds.bottom) {
|
||||
return (this.$refs.dropdownMenu.scrollTop =
|
||||
optionEl.offsetTop - (bounds.height - height));
|
||||
}
|
||||
}
|
||||
return pixelsToPointerTop;
|
||||
},
|
||||
|
||||
/**
|
||||
* The distance in pixels from the top of the dropdown
|
||||
* list to the bottom of the current pointer element.
|
||||
* @returns {*}
|
||||
*/
|
||||
pixelsToPointerBottom() {
|
||||
return this.pixelsToPointerTop() + this.pointerHeight();
|
||||
},
|
||||
|
||||
/**
|
||||
* The offsetHeight of the current pointer element.
|
||||
* @returns {number}
|
||||
*/
|
||||
pointerHeight() {
|
||||
let element = this.$refs.dropdownMenu
|
||||
? this.$refs.dropdownMenu.children[this.typeAheadPointer]
|
||||
: false;
|
||||
return element ? element.offsetHeight : 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* The currently viewable portion of the dropdownMenu.
|
||||
* @returns {{top: (string|*|number), bottom: *}}
|
||||
*/
|
||||
viewport() {
|
||||
return {
|
||||
top: this.$refs.dropdownMenu ? this.$refs.dropdownMenu.scrollTop : 0,
|
||||
bottom: this.$refs.dropdownMenu
|
||||
? this.$refs.dropdownMenu.offsetHeight +
|
||||
this.$refs.dropdownMenu.scrollTop
|
||||
: 0
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Scroll the dropdownMenu to a given position.
|
||||
* @param position
|
||||
* @returns {*}
|
||||
*/
|
||||
scrollTo(position) {
|
||||
getDropdownViewport() {
|
||||
return this.$refs.dropdownMenu
|
||||
? (this.$refs.dropdownMenu.scrollTop = position)
|
||||
: null;
|
||||
? this.$refs.dropdownMenu.getBoundingClientRect()
|
||||
: {
|
||||
height: 0,
|
||||
top: 0,
|
||||
bottom: 0
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user