<template>
<div :style="{ height: height + 'px', zIndex: zIndex }">
<div
:class="className"
:style="{
top: isSticky ? stickyTop + 'px' : '',
zIndex: zIndex,
position: position,
width: width,
height: height + 'px',
}"
>
<slot></slot>
</div>
</div>
</template>
<script>
export default {
name: "VabSticky",
props: {
stickyTop: {
type: Number,
default: 0,
},
zIndex: {
type: Number,
default: 1,
},
className: {
type: String,
default: "",
},
},
data() {
return {
active: false,
position: "",
width: undefined,
height: undefined,
isSticky: false,
};
},
mounted() {
this.height = this.$el.getBoundingClientRect().height;
window.addEventListener("scroll", this.handleScroll);
window.addEventListener("resize", this.handleResize);
},
activated() {
this.handleScroll();
},
destroyed() {
window.removeEventListener("scroll", this.handleScroll);
window.removeEventListener("resize", this.handleResize);
},
methods: {
sticky() {
if (this.active) {
return;
}
this.position = "fixed";
this.active = true;
this.width = this.width + "px";
this.isSticky = true;
},
handleReset() {
if (!this.active) {
return;
}
this.reset();
},
reset() {
this.position = "";
this.width = "auto";
this.active = false;
this.isSticky = false;
},
handleScroll() {
const width = this.$el.getBoundingClientRect().width;
this.width = width || "auto";
const offsetTop = this.$el.getBoundingClientRect().top;
if (offsetTop < this.stickyTop) {
this.sticky();
return;
}
this.handleReset();
},
handleResize() {
if (this.isSticky) {
this.width = this.$el.getBoundingClientRect().width + "px";
}
},
},
};
</script>