lin-view-ui
Version:
vue components library
585 lines (510 loc) • 18 kB
JavaScript
import ResizeObserver from 'resize-observer-polyfill';
import Spinner from './spinner.js';
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
var fails$2 = function (exec) {
try {
return !!exec();
} catch (error) {
return true;
}
};
var fails$1 = fails$2;
// Detect IE8's incomplete defineProperty implementation
var descriptors = !fails$1(function () {
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
return Object.defineProperty({}, 1, { get: function () { return 7; } })[1] != 7;
});
var objectDefineProperty = {};
var check = function (it) {
return it && it.Math == Math && it;
};
// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
var global$2 =
// eslint-disable-next-line es/no-global-this -- safe
check(typeof globalThis == 'object' && globalThis) ||
check(typeof window == 'object' && window) ||
// eslint-disable-next-line no-restricted-globals -- safe
check(typeof self == 'object' && self) ||
check(typeof commonjsGlobal == 'object' && commonjsGlobal) ||
// eslint-disable-next-line no-new-func -- fallback
(function () { return this; })() || Function('return this')();
var isObject$3 = function (it) {
return typeof it === 'object' ? it !== null : typeof it === 'function';
};
var global$1 = global$2;
var isObject$2 = isObject$3;
var document$1 = global$1.document;
// typeof document.createElement is 'object' in old IE
var EXISTS = isObject$2(document$1) && isObject$2(document$1.createElement);
var documentCreateElement = function (it) {
return EXISTS ? document$1.createElement(it) : {};
};
var DESCRIPTORS$2 = descriptors;
var fails = fails$2;
var createElement = documentCreateElement;
// Thank's IE8 for his funny defineProperty
var ie8DomDefine = !DESCRIPTORS$2 && !fails(function () {
// eslint-disable-next-line es/no-object-defineproperty -- requied for testing
return Object.defineProperty(createElement('div'), 'a', {
get: function () { return 7; }
}).a != 7;
});
var isObject$1 = isObject$3;
var anObject$1 = function (it) {
if (!isObject$1(it)) {
throw TypeError(String(it) + ' is not an object');
} return it;
};
var isObject = isObject$3;
// `ToPrimitive` abstract operation
// https://tc39.es/ecma262/#sec-toprimitive
// instead of the ES6 spec version, we didn't implement @@toPrimitive case
// and the second argument - flag - preferred type is a string
var toPrimitive$1 = function (input, PREFERRED_STRING) {
if (!isObject(input)) return input;
var fn, val;
if (PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val;
if (typeof (fn = input.valueOf) == 'function' && !isObject(val = fn.call(input))) return val;
if (!PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val;
throw TypeError("Can't convert object to primitive value");
};
var DESCRIPTORS$1 = descriptors;
var IE8_DOM_DEFINE = ie8DomDefine;
var anObject = anObject$1;
var toPrimitive = toPrimitive$1;
// eslint-disable-next-line es/no-object-defineproperty -- safe
var $defineProperty = Object.defineProperty;
// `Object.defineProperty` method
// https://tc39.es/ecma262/#sec-object.defineproperty
objectDefineProperty.f = DESCRIPTORS$1 ? $defineProperty : function defineProperty(O, P, Attributes) {
anObject(O);
P = toPrimitive(P, true);
anObject(Attributes);
if (IE8_DOM_DEFINE) try {
return $defineProperty(O, P, Attributes);
} catch (error) { /* empty */ }
if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported');
if ('value' in Attributes) O[P] = Attributes.value;
return O;
};
var DESCRIPTORS = descriptors;
var defineProperty = objectDefineProperty.f;
var FunctionPrototype = Function.prototype;
var FunctionPrototypeToString = FunctionPrototype.toString;
var nameRE = /^\s*function ([^ (]*)/;
var NAME = 'name';
// Function instances `.name` property
// https://tc39.es/ecma262/#sec-function-instances-name
if (DESCRIPTORS && !(NAME in FunctionPrototype)) {
defineProperty(FunctionPrototype, NAME, {
configurable: true,
get: function () {
try {
return FunctionPrototypeToString.call(this).match(nameRE)[1];
} catch (error) {
return '';
}
}
});
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
var script = {
name: "LinScrollBar",
components: _defineProperty({}, Spinner.name, Spinner),
props: {
// 是否一直显示自定义滚动条
hover: {
type: Boolean,
default: false
},
// 高度
height: {
type: String,
default: "100%"
},
// 宽度
width: {
type: String,
default: "100%"
},
// 最大高度
maxHeight: {
type: String
},
// 最小高度
minHeight: {
type: String
},
// 是否正在加载,显示加载动画
loading: {
type: Boolean,
default: false
},
// 加载文案
loadingText: String,
// 加载器大小
loadingSize: String
},
data: function data() {
return {
// 自定义滚动条高度
barHeight: 0,
// 自定义滚动条距离顶部距离
barTop: 0,
// 是否显示滚动条
showBar: false,
// 鼠标悬浮在容器中时候显示自定义滚动条
hoverBar: false
};
},
mounted: function mounted() {
// 内容容器高度
this.wrapperHeight = 0; // 内容高度
this.contentHeight = 0; // this.barWrapperHeight = 0;
// 自定义滚动条一开始所在位置
this.startY = 0; // 观察DOM元素变化实例对象
this.observer = null; // 标志位,鼠标是否可以进行移动了(能否拖拽)
this.isMove = false; // 鼠标是否离开容器
this.isLeave = false; // 初始化
this.init(); // 初始化DOM观察
this.initObserver();
},
methods: {
initObserver: function initObserver() {
var _this = this;
// DOM元素大小(宽高)发生变化的时候
this.observer = new ResizeObserver(function () {
_this.init();
});
this.observer.observe(this.$refs.content);
},
init: function init() {
this.initDom();
this.initBar();
},
// 获取相关DOM元素高度
initDom: function initDom() {
this.wrapperHeight = this.$refs.wrapper.clientHeight;
this.contentHeight = this.$refs.content.clientHeight;
},
// 初始化自定义滚动条
initBar: function initBar() {
var wrapperHeight = this.wrapperHeight,
contentHeight = this.contentHeight; // const { contentHeight } = this;
// 求 滚动条的高度
if (wrapperHeight / contentHeight < 1) {
// 内容高度大于容器高度
// 滚动条高度/容器高度 = 容器高度/内容高度
this.barHeight = wrapperHeight / contentHeight * wrapperHeight; // 此时需要显示自定义滚动条
this.showBar = true;
} else {
this.showBar = false;
}
if (this.showBar) {
// 如果需要显示自定义滚动条,要初始化滚动条的位置
var scrollTop = this.$refs.wrapper.scrollTop; // 算出自定义滚动条,相对于容器的y轴位置
var percent = scrollTop / contentHeight;
var barTop = percent * wrapperHeight;
this.barTop = barTop;
}
},
// 监听容器的滚动事件
onWrapperScroll: function onWrapperScroll(event) {
var contentHeight = this.contentHeight,
wrapperHeight = this.wrapperHeight; // const { wrapperHeight } = this;
var scrollTop = event.target.scrollTop; // 算出自定义滚动条,相对于容器的y轴位置
var percent = scrollTop / (contentHeight - wrapperHeight);
var barTop = percent * (wrapperHeight - this.barHeight);
this.barTop = barTop;
this.$emit("scroll", event);
if (scrollTop + wrapperHeight >= contentHeight) {
// 滚动到底部
this.$emit("scrollToBottom", event);
}
},
// 鼠标按下事件
onMouseDown: function onMouseDown(event) {
// 标志位
this.isMove = true; // 给body添加样式,不能让鼠标在移动的时候选中文字,否则会造成鼠标抬起事件丢失
document.getElementsByTagName("body")[0].classList.add("user-no-select"); // 记录鼠标点击的初始位置
this.startY = event.clientY; // 监听鼠标移动事件和抬起事件
document.addEventListener("mousemove", this.onMousemove);
document.addEventListener("mouseup", this.onMouseup);
},
// 鼠标移动事件
onMousemove: function onMousemove(event) {
// 纵轴坐标
var topY = event.clientY - this.startY; // 计算自定义滚动条应该距离顶部多少
var barTop = this.$refs.bar.offsetTop + topY; // 更新位置
this.updatePosition(barTop);
this.startY = event.clientY;
},
// 鼠标抬起事件
onMouseup: function onMouseup() {
// 标志位,此时应该不能再进行拖拽了
this.isMove = false;
if (this.isLeave) {
this.hoverBar = false;
} // 取消鼠标按下时添加的样式
document.getElementsByTagName("body")[0].classList.remove("user-no-select"); // 注销事件
document.removeEventListener("mousemove", this.onMousemove);
document.removeEventListener("mouseup", this.onMouseup);
},
updatePosition: function updatePosition(barTop) {
var wrapperHeight = this.wrapperHeight,
contentHeight = this.contentHeight; // const { contentHeight } = this;
var barHeight = this.$refs.bar.clientHeight; // 边界情况处理
if (barTop >= wrapperHeight - barHeight) {
barTop = wrapperHeight - barHeight;
}
if (barTop <= 0) {
barTop = 0;
}
this.barTop = barTop; // 自定义滚动条位置发生了变化,容器也要相对应进行移动
var percent = barTop / wrapperHeight;
var contentTop = percent * contentHeight;
this.$refs.wrapper.scrollTop = contentTop;
},
// 鼠标进入事件
onMouseEnter: function onMouseEnter() {
this.hoverBar = true;
this.isLeave = false;
},
// 鼠标离开事件
onMouseLeave: function onMouseLeave() {
this.isLeave = true;
if (!this.isMove) {
this.hoverBar = false;
}
},
// 点击自定义滚动条
onBarWrapperClick: function onBarWrapperClick(event) {
// 获取点击位置
var clientY = event.clientY; // 获取容器距离页面的距离
var marginTop = this.$refs.wrapper.getBoundingClientRect().top; // 计算出鼠标点击的位置距离容器顶部的距离,this.barHeight / 2 是为了让滚动条移动后,鼠标位于滚动条中间
this.updatePosition(clientY - marginTop - this.barHeight / 2);
}
},
computed: {
// 根节点样式
style: function style() {
var style = {};
if (this.height) {
style.height = this.height;
}
if (this.maxHeight) {
style["max-height"] = this.maxHeight;
}
if (this.minHeight) {
style["min-height"] = this.minHeight;
}
return style;
}
},
beforeDestroy: function beforeDestroy() {
if (this.observer) {
this.observer.disconnect();
this.observer = null;
}
document.removeEventListener("mousemove", this.onMousemove);
document.removeEventListener("mouseup", this.onMouseup);
}
};
function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier /* server only */, shadowMode, createInjector, createInjectorSSR, createInjectorShadow) {
if (typeof shadowMode !== 'boolean') {
createInjectorSSR = createInjector;
createInjector = shadowMode;
shadowMode = false;
}
// Vue.extend constructor export interop.
const options = typeof script === 'function' ? script.options : script;
// render functions
if (template && template.render) {
options.render = template.render;
options.staticRenderFns = template.staticRenderFns;
options._compiled = true;
// functional template
if (isFunctionalTemplate) {
options.functional = true;
}
}
// scopedId
if (scopeId) {
options._scopeId = scopeId;
}
let hook;
if (moduleIdentifier) {
// server build
hook = function (context) {
// 2.3 injection
context =
context || // cached call
(this.$vnode && this.$vnode.ssrContext) || // stateful
(this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext); // functional
// 2.2 with runInNewContext: true
if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
context = __VUE_SSR_CONTEXT__;
}
// inject component styles
if (style) {
style.call(this, createInjectorSSR(context));
}
// register component module identifier for async chunk inference
if (context && context._registeredComponents) {
context._registeredComponents.add(moduleIdentifier);
}
};
// used by ssr in case component is cached and beforeCreate
// never gets called
options._ssrRegister = hook;
}
else if (style) {
hook = shadowMode
? function (context) {
style.call(this, createInjectorShadow(context, this.$root.$options.shadowRoot));
}
: function (context) {
style.call(this, createInjector(context));
};
}
if (hook) {
if (options.functional) {
// register for functional component in vue file
const originalRender = options.render;
options.render = function renderWithStyleInjection(h, context) {
hook.call(context);
return originalRender(h, context);
};
}
else {
// inject component registration as beforeCreate hook
const existing = options.beforeCreate;
options.beforeCreate = existing ? [].concat(existing, hook) : [hook];
}
}
return script;
}
/* script */
const __vue_script__ = script;
/* template */
var __vue_render__ = function() {
var _vm = this;
var _h = _vm.$createElement;
var _c = _vm._self._c || _h;
return _c(
"div",
{
staticClass: "lin-scroll-bar",
style: Object.assign({}, _vm.style, { width: _vm.width }),
on: { mouseenter: _vm.onMouseEnter, mouseleave: _vm.onMouseLeave }
},
[
_c(
"div",
{
ref: "wrapper",
staticClass: "lin-scroll-bar-wrapper",
style: _vm.style,
on: { scroll: _vm.onWrapperScroll }
},
[
_c(
"div",
{ ref: "content", staticClass: "lin-scroll-bar-content" },
[
_vm._t("default"),
_vm._v(" "),
_vm.loading
? _c(
"div",
{ staticClass: "lin-scroll-bar-spinner" },
[
_vm._t("loading", function() {
return [
_c("lin-spinner", {
attrs: {
text: _vm.loadingText,
size: _vm.loadingSize
}
})
]
})
],
2
)
: _vm._e()
],
2
)
]
),
_vm._v(" "),
_vm.showBar
? _c(
"div",
{
staticClass: "lin-srcoll-bar-barwrapper",
on: { click: _vm.onBarWrapperClick }
},
[
_c("div", {
directives: [
{
name: "show",
rawName: "v-show",
value: _vm.hoverBar || _vm.hover,
expression: "hoverBar || hover"
}
],
ref: "bar",
staticClass: "lin-srcoll-bar-bar",
style: { height: _vm.barHeight + "px", top: _vm.barTop + "px" },
on: { mousedown: _vm.onMouseDown }
})
]
)
: _vm._e()
]
)
};
var __vue_staticRenderFns__ = [];
__vue_render__._withStripped = true;
/* style */
const __vue_inject_styles__ = undefined;
/* scoped */
const __vue_scope_id__ = undefined;
/* module identifier */
const __vue_module_identifier__ = undefined;
/* functional template */
const __vue_is_functional_template__ = false;
/* style inject */
/* style inject SSR */
/* style inject shadow dom */
const __vue_component__ = /*#__PURE__*/normalizeComponent(
{ render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
__vue_inject_styles__,
__vue_script__,
__vue_scope_id__,
__vue_is_functional_template__,
__vue_module_identifier__,
false,
undefined,
undefined,
undefined
);
__vue_component__.install = function (Vue) {
return Vue.component(__vue_component__.name, __vue_component__);
};
export default __vue_component__;