@openhab-ui/setup-and-maintenance
Version:
Configuration and maintenance interface for openHAB
1,390 lines (1,178 loc) • 36.7 kB
JavaScript
import '../vue.js';
var config = {
itemsLimit: 1000
};
var ResizeObserver = {
render: function render() {
var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c('div', { staticClass: "resize-observer", attrs: { "tabindex": "-1" } });
}, staticRenderFns: [], _scopeId: 'data-v-b329ee4c',
name: 'resize-observer',
methods: {
compareAndNotify: function compareAndNotify() {
if (this._w !== this.$el.offsetWidth || this._h !== this.$el.offsetHeight) {
this._w = this.$el.offsetWidth;
this._h = this.$el.offsetHeight;
this.$emit('notify');
}
},
addResizeHandlers: function addResizeHandlers() {
this._resizeObject.contentDocument.defaultView.addEventListener('resize', this.compareAndNotify, { passive: true });
this.compareAndNotify();
},
removeResizeHandlers: function removeResizeHandlers() {
if (this._resizeObject && this._resizeObject.onload) {
if (this._resizeObject.contentDocument) {
this._resizeObject.contentDocument.defaultView.removeEventListener('resize', this.compareAndNotify, { passive: true });
}
delete this._resizeObject.onload;
}
}
},
mounted: function mounted() {
var _this = this;
this.$nextTick(function () {
_this._w = _this.$el.offsetWidth;
_this._h = _this.$el.offsetHeight;
});
var object = document.createElement('object');
this._resizeObject = object;
object.setAttribute('aria-hidden', 'true');
object.setAttribute('tabindex', -1);
object.onload = this.addResizeHandlers;
object.type = 'text/html';
object.data = 'about:blank';
this.$el.appendChild(object);
},
beforeDestroy: function beforeDestroy() {
this.removeResizeHandlers();
}
};
// Install the components
function install(Vue$$1) {
Vue$$1.component('resize-observer', ResizeObserver);
Vue$$1.component('ResizeObserver', ResizeObserver);
}
// Plugin
var plugin$2 = {
// eslint-disable-next-line no-undef
version: "0.4.5",
install: install
};
// Auto-install
var GlobalVue$1 = null;
if (typeof window !== 'undefined') {
GlobalVue$1 = window.Vue;
} else if (typeof global !== 'undefined') {
GlobalVue$1 = global.Vue;
}
if (GlobalVue$1) {
GlobalVue$1.use(plugin$2);
}
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
var toConsumableArray = function (arr) {
if (Array.isArray(arr)) {
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
return arr2;
} else {
return Array.from(arr);
}
};
function processOptions(value) {
var options = void 0;
if (typeof value === 'function') {
// Simple options (callback-only)
options = {
callback: value
};
} else {
// Options object
options = value;
}
return options;
}
function throttle(callback, delay) {
var timeout = void 0;
var lastState = void 0;
var currentArgs = void 0;
var throttled = function throttled(state) {
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
currentArgs = args;
if (timeout && state === lastState) return;
lastState = state;
clearTimeout(timeout);
timeout = setTimeout(function () {
callback.apply(undefined, [state].concat(toConsumableArray(currentArgs)));
timeout = 0;
}, delay);
};
throttled._clear = function () {
clearTimeout(timeout);
};
return throttled;
}
function deepEqual(val1, val2) {
if (val1 === val2) return true;
if ((typeof val1 === 'undefined' ? 'undefined' : _typeof(val1)) === 'object') {
for (var key in val1) {
if (!deepEqual(val1[key], val2[key])) {
return false;
}
}
return true;
}
return false;
}
var VisibilityState = function () {
function VisibilityState(el, options, vnode) {
classCallCheck(this, VisibilityState);
this.el = el;
this.observer = null;
this.frozen = false;
this.createObserver(options, vnode);
}
createClass(VisibilityState, [{
key: 'createObserver',
value: function createObserver(options, vnode) {
var _this = this;
if (this.observer) {
this.destroyObserver();
}
if (this.frozen) return;
this.options = processOptions(options);
this.callback = this.options.callback;
// Throttle
if (this.callback && this.options.throttle) {
this.callback = throttle(this.callback, this.options.throttle);
}
this.oldResult = undefined;
this.observer = new IntersectionObserver(function (entries) {
var entry = entries[0];
if (_this.callback) {
// Use isIntersecting if possible because browsers can report isIntersecting as true, but intersectionRatio as 0, when something very slowly enters the viewport.
var result = entry.isIntersecting && entry.intersectionRatio >= _this.threshold;
if (result === _this.oldResult) return;
_this.oldResult = result;
_this.callback(result, entry);
if (result && _this.options.once) {
_this.frozen = true;
_this.destroyObserver();
}
}
}, this.options.intersection);
// Wait for the element to be in document
vnode.context.$nextTick(function () {
_this.observer.observe(_this.el);
});
}
}, {
key: 'destroyObserver',
value: function destroyObserver() {
if (this.observer) {
this.observer.disconnect();
this.observer = null;
}
// Cancel throttled call
if (this.callback && this.callback._clear) {
this.callback._clear();
this.callback = null;
}
}
}, {
key: 'threshold',
get: function get$$1() {
return this.options.intersection && this.options.intersection.threshold || 0;
}
}]);
return VisibilityState;
}();
function bind(el, _ref, vnode) {
var value = _ref.value;
if (typeof IntersectionObserver === 'undefined') {
console.warn('[vue-observe-visibility] IntersectionObserver API is not available in your browser. Please install this polyfill: https://github.com/w3c/IntersectionObserver/tree/master/polyfill');
} else {
var state = new VisibilityState(el, value, vnode);
el._vue_visibilityState = state;
}
}
function update(el, _ref2, vnode) {
var value = _ref2.value,
oldValue = _ref2.oldValue;
if (deepEqual(value, oldValue)) return;
var state = el._vue_visibilityState;
if (state) {
state.createObserver(value, vnode);
} else {
bind(el, { value: value }, vnode);
}
}
function unbind(el) {
var state = el._vue_visibilityState;
if (state) {
state.destroyObserver();
delete el._vue_visibilityState;
}
}
var ObserveVisibility = {
bind: bind,
update: update,
unbind: unbind
};
// Install the components
function install$1(Vue$$1) {
Vue$$1.directive('observe-visibility', ObserveVisibility);
/* -- Add more components here -- */
}
/* -- Plugin definition & Auto-install -- */
/* You shouldn't have to modify the code below */
// Plugin
var plugin$4 = {
// eslint-disable-next-line no-undef
version: "0.4.3",
install: install$1
};
// Auto-install
var GlobalVue$2 = null;
if (typeof window !== 'undefined') {
GlobalVue$2 = window.Vue;
} else if (typeof global !== 'undefined') {
GlobalVue$2 = global.Vue;
}
if (GlobalVue$2) {
GlobalVue$2.use(plugin$4);
}
var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function createCommonjsModule(fn, module) {
return module = { exports: {} }, fn(module, module.exports), module.exports;
}
var scrollparent = createCommonjsModule(function (module) {
(function (root, factory) {
if (module.exports) {
module.exports = factory();
} else {
root.Scrollparent = factory();
}
}(commonjsGlobal, function () {
var regex = /(auto|scroll)/;
var parents = function (node, ps) {
if (node.parentNode === null) { return ps; }
return parents(node.parentNode, ps.concat([node]));
};
var style = function (node, prop) {
return getComputedStyle(node, null).getPropertyValue(prop);
};
var overflow = function (node) {
return style(node, "overflow") + style(node, "overflow-y") + style(node, "overflow-x");
};
var scroll = function (node) {
return regex.test(overflow(node));
};
var scrollParent = function (node) {
if (!(node instanceof HTMLElement || node instanceof SVGElement)) {
return;
}
var ps = parents(node.parentNode, []);
for (var i = 0; i < ps.length; i += 1) {
if (scroll(ps[i])) {
return ps[i];
}
}
return document.scrollingElement || document.documentElement;
};
return scrollParent;
}));
});
if (typeof window !== 'undefined') {
try {
var opts = Object.defineProperty({}, 'passive', {
get: function get() {
}
});
window.addEventListener('test', null, opts);
} catch (e) { }
}
// @vue/component
var Scroller = {
components: {
ResizeObserver: ResizeObserver
},
directives: {
ObserveVisibility: ObserveVisibility
},
props: {
items: {
type: Array,
required: true
},
itemHeight: {
type: Number,
default: null
},
minItemHeight: {
type: [Number, String],
default: null
},
heightField: {
type: String,
default: 'height'
},
typeField: {
type: String,
default: 'type'
},
keyField: {
type: String,
default: 'id'
},
buffer: {
type: Number,
default: 200
},
pageMode: {
type: Boolean,
default: false
},
prerender: {
type: Number,
default: 0
},
emitUpdate: {
type: Boolean,
default: false
}
},
computed: {
heights: function heights() {
if (this.itemHeight === null) {
var heights = {
'-1': { accumulator: 0 }
};
var items = this.items;
var field = this.heightField;
var minItemHeight = this.minItemHeight;
var accumulator = 0;
var current = void 0;
for (var i = 0, l = items.length; i < l; i++) {
current = items[i][field] || minItemHeight;
accumulator += current;
heights[i] = { accumulator: accumulator, height: current };
}
return heights;
}
return [];
}
},
beforeDestroy: function beforeDestroy() {
this.removeListeners();
},
methods: {
getListenerTarget: function getListenerTarget() {
var target = scrollparent(this.$el);
// Fix global scroll target for Chrome and Safari
if (target === window.document.documentElement || target === window.document.body) {
target = window;
}
return target;
},
getScroll: function getScroll() {
var el = this.$el;
// const wrapper = this.$refs.wrapper
var scrollState = void 0;
if (this.pageMode) {
var size = el.getBoundingClientRect();
var top = -size.top;
var height = window.innerHeight;
if (top < 0) {
height += top;
top = 0;
}
if (top + height > size.height) {
height = size.height - top;
}
scrollState = {
top: top,
bottom: top + height
};
} else {
scrollState = {
top: el.scrollTop,
bottom: el.scrollTop + el.clientHeight
};
}
return scrollState;
},
applyPageMode: function applyPageMode() {
if (this.pageMode) {
this.addListeners();
} else {
this.removeListeners();
}
},
addListeners: function addListeners() {
this.listenerTarget = this.getListenerTarget();
this.listenerTarget.addEventListener('scroll', this.handleScroll, { passive: true });
this.listenerTarget.addEventListener('resize', this.handleResize, { passive: true });
},
removeListeners: function removeListeners() {
if (!this.listenerTarget) {
return;
}
this.listenerTarget.removeEventListener('scroll', this.handleScroll, { passive: true });
this.listenerTarget.removeEventListener('resize', this.handleResize, { passive: true });
this.listenerTarget = null;
},
scrollToItem: function scrollToItem(index) {
var scrollTop = void 0;
if (this.itemHeight === null) {
scrollTop = index > 0 ? this.heights[index - 1].accumulator : 0;
} else {
scrollTop = index * this.itemHeight;
}
this.scrollToPosition(scrollTop);
},
scrollToPosition: function scrollToPosition(position) {
this.$el.scrollTop = position;
},
itemsLimitError: function itemsLimitError() {
var _this = this;
setTimeout(function () {
console.log('It seems the scroller element isn\'t scrolling, so it tries to render all the items at once.', 'Scroller:', _this.$el);
console.log('Make sure the scroller has a fixed height and \'overflow-y\' set to \'auto\' so it can scroll correctly and only render the items visible in the scroll viewport.');
});
throw new Error('Rendered items limit reached');
}
}
};
var uid = 0;
var RecycleScroller = {
render: function render() {
var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c('div', {
directives: [{ name: "observe-visibility", rawName: "v-observe-visibility", value: _vm.handleVisibilityChange, expression: "handleVisibilityChange" }], staticClass: "vue-recycle-scroller", class: { ready: _vm.ready, 'page-mode': _vm.pageMode }, on: {
"&scroll": function scroll($event) {
return _vm.handleScroll($event);
}
}
}, [_vm._t("before-container"), _vm._v(" "), _c('div', { ref: "wrapper", staticClass: "vue-recycle-scroller__item-wrapper", style: { height: _vm.totalHeight + 'px' } }, _vm._l(_vm.pool, function (view) {
return _c('div', {
key: view.nr.id, staticClass: "vue-recycle-scroller__item-view", class: { hover: _vm.hoverKey === view.nr.key }, style: _vm.ready ? { transform: 'translateY(' + view.top + 'px)' } : null, on: {
"mouseenter": function mouseenter($event) {
_vm.hoverKey = view.nr.key;
}, "mouseleave": function mouseleave($event) {
_vm.hoverKey = null;
}
}
}, [_vm._t("default", null, { item: view.item, index: view.nr.index, active: view.nr.used })], 2);
}), 0), _vm._v(" "), _vm._t("after-container"), _vm._v(" "), _c('ResizeObserver', { on: { "notify": _vm.handleResize } })], 2);
}, staticRenderFns: [],
name: 'RecycleScroller',
mixins: [Scroller],
data: function data() {
return {
pool: [],
totalHeight: 0,
ready: false,
hoverKey: null
};
},
watch: {
items: function items() {
this.updateVisibleItems(true);
},
pageMode: function pageMode() {
this.applyPageMode();
this.updateVisibleItems(false);
},
heights: {
handler: function handler() {
this.updateVisibleItems(false);
},
deep: true
}
},
created: function created() {
this.$_startIndex = 0;
this.$_endIndex = 0;
this.$_views = new Map();
this.$_unusedViews = new Map();
this.$_scrollDirty = false;
if (this.$isServer) {
this.updateVisibleItems(false);
}
},
mounted: function mounted() {
var _this = this;
this.applyPageMode();
this.$nextTick(function () {
_this.updateVisibleItems(true);
_this.ready = true;
});
},
methods: {
addView: function addView(pool, index, item, key, type) {
var view = {
item: item,
top: 0
};
var nonReactive = {
id: uid++,
index: index,
used: true,
key: key,
type: type
};
Object.defineProperty(view, 'nr', {
configurable: false,
value: nonReactive
});
pool.push(view);
return view;
},
unuseView: function unuseView(view) {
var fake = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var unusedViews = this.$_unusedViews;
var type = view.nr.type;
var unusedPool = unusedViews.get(type);
if (!unusedPool) {
unusedPool = [];
unusedViews.set(type, unusedPool);
}
unusedPool.push(view);
if (!fake) {
view.nr.used = false;
view.top = -9999;
this.$_views.delete(view.nr.key);
}
},
handleResize: function handleResize() {
this.$emit('resize');
if (this.ready) this.updateVisibleItems(false);
},
handleScroll: function handleScroll(event) {
if (!this.$_scrollDirty) {
this.$_scrollDirty = true;
requestAnimationFrame(() => {
this.$_scrollDirty = false;
var _updateVisibleItems = this.updateVisibleItems(false),
continuous = _updateVisibleItems.continuous;
this.$emit('scrolled', this.$_startIndex, this.$_endIndex, this.items.length);
// It seems sometimes chrome doesn't fire scroll event :/
// When non continous scrolling is ending, we force a refresh
if (!continuous) {
clearTimeout(this.$_refreshTimout);
this.$_refreshTimout = setTimeout(this.handleScroll, 100);
}
});
}
},
handleVisibilityChange: function handleVisibilityChange(isVisible, entry) {
var _this3 = this;
if (this.ready) {
if (isVisible || entry.boundingClientRect.width !== 0 || entry.boundingClientRect.height !== 0) {
this.$emit('visible');
requestAnimationFrame(function () {
_this3.updateVisibleItems(false);
});
} else {
this.$emit('hidden');
}
}
},
updateVisibleItems: function updateVisibleItems(checkItem) {
var itemHeight = this.itemHeight;
var typeField = this.typeField;
var keyField = this.keyField;
var items = this.items;
var count = items.length;
var heights = this.heights;
var views = this.$_views;
var unusedViews = this.$_unusedViews;
var pool = this.pool;
var startIndex = void 0,
endIndex = void 0;
var totalHeight = void 0;
if (!count) {
startIndex = endIndex = totalHeight = 0;
} else if (this.$isServer) {
startIndex = 0;
endIndex = this.prerender;
totalHeight = null;
} else {
var scroll = this.getScroll();
var buffer = this.buffer;
scroll.top -= buffer;
scroll.bottom += buffer;
// Variable height mode
if (itemHeight === null) {
var h = void 0;
var a = 0;
var b = count - 1;
var i = ~~(count / 2);
var oldI = void 0;
// Searching for startIndex
do {
oldI = i;
h = heights[i].accumulator;
if (h < scroll.top) {
a = i;
} else if (i < count - 1 && heights[i + 1].accumulator > scroll.top) {
b = i;
}
i = ~~((a + b) / 2);
} while (i !== oldI);
i < 0 && (i = 0);
startIndex = i;
// For container style
totalHeight = heights[count - 1].accumulator;
// Searching for endIndex
for (endIndex = i; endIndex < count && heights[endIndex].accumulator < scroll.bottom; endIndex++) { }
if (endIndex === -1) {
endIndex = items.length - 1;
} else {
endIndex++;
// Bounds
endIndex > count && (endIndex = count);
}
} else {
// Fixed height mode
startIndex = ~~(scroll.top / itemHeight);
endIndex = Math.ceil(scroll.bottom / itemHeight);
// Bounds
startIndex < 0 && (startIndex = 0);
endIndex > count && (endIndex = count);
totalHeight = count * itemHeight;
}
}
if (endIndex - startIndex > config.itemsLimit) {
this.itemsLimitError();
}
this.totalHeight = totalHeight;
var view = void 0;
var continuous = startIndex <= this.$_endIndex && endIndex >= this.$_startIndex;
var unusedIndex = void 0;
if (this.$_continuous !== continuous) {
if (continuous) {
views.clear();
unusedViews.clear();
for (var _i = 0, l = pool.length; _i < l; _i++) {
view = pool[_i];
this.unuseView(view);
}
}
this.$_continuous = continuous;
} else if (continuous) {
for (var _i2 = 0, _l = pool.length; _i2 < _l; _i2++) {
view = pool[_i2];
if (view.nr.used) {
// Update view item index
if (checkItem) {
view.nr.index = items.findIndex(function (item) {
return keyField ? item[keyField] === view.item[keyField] : item === view.item;
});
}
// Check if index is still in visible range
if (view.nr.index === -1 || view.nr.index < startIndex || view.nr.index >= endIndex) {
this.unuseView(view);
}
}
}
}
if (!continuous) {
unusedIndex = new Map();
}
var item = void 0,
type = void 0,
unusedPool = void 0;
var v = void 0;
for (var _i3 = startIndex; _i3 < endIndex; _i3++) {
item = items[_i3];
var key = keyField ? item[keyField] : item;
view = views.get(key);
if (!itemHeight && !heights[_i3].height) {
if (view) this.unuseView(view);
continue;
}
// No view assigned to item
if (!view) {
type = item[typeField];
if (continuous) {
unusedPool = unusedViews.get(type);
// Reuse existing view
if (unusedPool && unusedPool.length) {
view = unusedPool.pop();
view.item = item;
view.nr.used = true;
view.nr.index = _i3;
view.nr.key = key;
view.nr.type = type;
} else {
view = this.addView(pool, _i3, item, key, type);
}
} else {
unusedPool = unusedViews.get(type);
v = unusedIndex.get(type) || 0;
// Use existing view
// We don't care if they are already used
// because we are not in continous scrolling
if (unusedPool && v < unusedPool.length) {
view = unusedPool[v];
view.item = item;
view.nr.used = true;
view.nr.index = _i3;
view.nr.key = key;
view.nr.type = type;
unusedIndex.set(type, v + 1);
} else {
view = this.addView(pool, _i3, item, key, type);
this.unuseView(view, true);
}
v++;
}
views.set(key, view);
} else {
view.nr.used = true;
view.item = item;
}
// Update position
if (itemHeight === null) {
view.top = heights[_i3 - 1].accumulator;
} else {
view.top = _i3 * itemHeight;
}
}
this.$_startIndex = startIndex;
this.$_endIndex = endIndex;
if (this.emitUpdate) this.$emit('update', startIndex, endIndex);
return {
continuous: continuous
};
}
}
};
var DynamicScroller = {
render: function render() {
var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c('RecycleScroller', _vm._g(_vm._b({
ref: "scroller", attrs: { "items": _vm.itemsWithHeight, "min-item-height": _vm.minItemHeight }, on: { "resize": _vm.onScrollerResize, "visible": _vm.onScrollerVisible }, scopedSlots: _vm._u([{
key: "default", fn: function fn(_ref) {
var itemWithHeight = _ref.item,
index = _ref.index,
active = _ref.active;
return [_vm._t("default", null, null, {
item: itemWithHeight.item,
index: index,
active: active,
itemWithHeight: itemWithHeight
})];
}
}])
}, 'RecycleScroller', _vm.$attrs, false), _vm.listeners), [_c('template', { slot: "before-container" }, [_vm._t("before-container")], 2), _vm._v(" "), _c('template', { slot: "after-container" }, [_vm._t("after-container")], 2)], 2);
}, staticRenderFns: [],
name: 'DynamicScroller',
components: {
RecycleScroller: RecycleScroller
},
inheritAttrs: false,
provide: function provide() {
return {
vscrollData: this.vscrollData,
vscrollBus: this
};
},
props: {
items: {
type: Array,
required: true
},
minItemHeight: {
type: [Number, String],
required: true
},
keyField: {
type: String,
default: 'id'
}
},
data: function data() {
return {
vscrollData: {
active: true,
heights: {},
keyField: this.keyField
}
};
},
computed: {
itemsWithHeight: function itemsWithHeight() {
var result = [];
var items = this.items;
var keyField = this.keyField;
var heights = this.vscrollData.heights;
for (var i = 0; i < items.length; i++) {
var item = items[i];
var id = item[keyField];
result.push({
item: item,
id: id,
height: heights[id] || 0
});
}
return result;
},
listeners: function listeners() {
var listeners = {};
for (var key in this.$listeners) {
if (key !== 'resize' && key !== 'visible') {
listeners[key] = this.$listeners[key];
}
}
return listeners;
}
},
watch: {
items: 'forceUpdate'
},
created: function created() {
this.$_updates = [];
},
mounted: function mounted() {
var scroller = this.$refs.scroller;
var rect = this.getSize(scroller);
this._scrollerWidth = rect.width;
},
activated: function activated() {
this.vscrollData.active = true;
},
deactivated: function deactivated() {
this.vscrollData.active = false;
},
methods: {
onScrollerResize: function onScrollerResize() {
var scroller = this.$refs.scroller;
if (scroller) {
this.forceUpdate();
}
this.$emit('resize');
},
onScrollerVisible: function onScrollerVisible() {
this.$emit('vscroll:update', { force: false });
this.$emit('visible');
},
forceUpdate: function forceUpdate() {
this.vscrollData.heights = {};
this.$emit('vscroll:update', { force: true });
},
getSize: function getSize(scroller) {
return scroller.$el.getBoundingClientRect();
},
scrollToItem: function scrollToItem(index) {
var scroller = this.$refs.scroller;
if (scroller) scroller.scrollToItem(index);
}
}
};
var DynamicScrollerItem = {
name: 'DynamicScrollerItem',
inject: ['vscrollData', 'vscrollBus'],
props: {
item: {
type: Object,
required: true
},
watchData: {
type: Boolean,
default: false
},
active: {
type: Boolean,
required: true
},
sizeDependencies: {
type: [Array, Object],
default: null
},
emitResize: {
type: Boolean,
default: false
},
tag: {
type: String,
default: 'div'
}
},
computed: {
id: function id() {
return this.item[this.vscrollData.keyField];
},
height: function height() {
return this.vscrollData.heights[this.id] || 0;
}
},
watch: {
watchData: 'updateWatchData',
id: function id() {
if (!this.height) {
this.onDataUpdate();
}
},
active: function active(value) {
if (value && this.$_pendingVScrollUpdate) {
this.updateSize();
}
}
},
created: function created() {
var _this = this;
if (this.$isServer) return;
this.$_forceNextVScrollUpdate = false;
this.updateWatchData();
var _loop = function _loop(k) {
_this.$watch(function () {
return _this.sizeDependencies[k];
}, _this.onDataUpdate);
};
for (var k in this.sizeDependencies) {
_loop(k);
}
this.vscrollBus.$on('vscroll:update', this.onVscrollUpdate);
this.vscrollBus.$on('vscroll:update-size', this.onVscrollUpdateSize);
},
mounted: function mounted() {
if (this.vscrollData.active) {
this.updateSize();
}
},
beforeDestroy: function beforeDestroy() {
this.vscrollBus.$off('vscroll:update', this.onVscrollUpdate);
this.vscrollBus.$off('vscroll:update-size', this.onVscrollUpdateSize);
},
methods: {
updateSize: function updateSize() {
if (this.active && this.vscrollData.active) {
if (!this.$_pendingSizeUpdate) {
this.$_pendingSizeUpdate = true;
this.$_forceNextVScrollUpdate = false;
this.$_pendingVScrollUpdate = false;
if (this.active && this.vscrollData.active) {
this.computeSize(this.id);
}
}
} else {
this.$_forceNextVScrollUpdate = true;
}
},
getSize: function getSize() {
return this.$el.getBoundingClientRect();
},
updateWatchData: function updateWatchData() {
var _this2 = this;
if (this.watchData) {
this.$_watchData = this.$watch('data', function () {
_this2.onDataUpdate();
}, {
deep: true
});
} else if (this.$_watchData) {
this.$_watchData();
this.$_watchData = null;
}
},
onVscrollUpdate: function onVscrollUpdate(_ref) {
var force = _ref.force;
if (!this.active && force) {
this.$_pendingVScrollUpdate = true;
}
if (this.$_forceNextVScrollUpdate || force || !this.height) {
this.updateSize();
}
},
onDataUpdate: function onDataUpdate() {
this.updateSize();
},
computeSize: function computeSize(id) {
var _this3 = this;
this.$nextTick(function () {
if (_this3.id === id) {
var size = _this3.getSize();
if (size.height && _this3.height !== size.height) {
_this3.$set(_this3.vscrollData.heights, _this3.id, size.height);
if (_this3.emitResize) _this3.$emit('resize', _this3.id);
}
}
_this3.$_pendingSizeUpdate = false;
});
}
},
render: function render(h) {
return h(this.tag, this.$slots.default);
}
};
function registerComponents(Vue$$1, prefix) {
Vue$$1.component(prefix + 'recycle-scroller', RecycleScroller);
Vue$$1.component(prefix + 'RecycleScroller', RecycleScroller);
Vue$$1.component(prefix + 'dynamic-scroller', DynamicScroller);
Vue$$1.component(prefix + 'DynamicScroller', DynamicScroller);
Vue$$1.component(prefix + 'dynamic-scroller-item', DynamicScrollerItem);
Vue$$1.component(prefix + 'DynamicScrollerItem', DynamicScrollerItem);
}
var plugin = {
// eslint-disable-next-line no-undef
version: "1.0.0-beta.4",
install: function install(Vue$$1, options) {
var finalOptions = Object.assign({}, {
installComponents: true,
componentsPrefix: ''
}, options);
for (var key in finalOptions) {
if (typeof finalOptions[key] !== 'undefined') {
config[key] = finalOptions[key];
}
}
if (finalOptions.installComponents) {
registerComponents(Vue$$1, finalOptions.componentsPrefix);
}
}
};
// Auto-install
var GlobalVue = null;
if (typeof window !== 'undefined') {
GlobalVue = window.Vue;
} else if (typeof global !== 'undefined') {
GlobalVue = global.Vue;
}
if (GlobalVue) {
GlobalVue.use(plugin);
}
/**
* Generate articial logs via https://next.json-generator.com. Pattern:
[
{
'repeat(100)': {
_id: '{{index()}}',
timestamp: '{{date(new Date(2014, 0, 1), new Date()).getTime()}}',
level: '{{random("INFO", "DEBUG", "WARN", "TRACE")}}',
source: function (tags, parent) {return lorem(3, "word").replace(/ /g,".");} ,
message: '{{lorem(1, "sentences")}}',
}
}
]
*/
const Mixin = {
mounted: function () {
this.dateTimeFormat = new Intl.DateTimeFormat(navigator.language, {
year: 'numeric', month: 'numeric', day: 'numeric',
hour: 'numeric', minute: 'numeric', second: 'numeric'
});
this.setFilter("");
},
data: function () {
return {
items: [],
filtered: [],
filterString: null
}
},
components: { 'dynamic-scroller': DynamicScroller, 'dynamic-scroller-item': DynamicScrollerItem },
methods: {
setFilter(filterString) {
if (!filterString || filterString == "") {
this.filterString = null;
this.filtered = this.items;
return;
}
this.filterString = filterString;
let newFilteredItems = [];
for (let item of this.items)
if (this.filterPass(item)) newFilteredItems.push(item);
this.filtered = newFilteredItems;
},
filterPass(item) {
if (!this.filterString) return true;
return item.message.match(this.filterString);
},
newData(websocketData) {
websocketData = websocketData.detail;
if (!websocketData || websocketData.t !== "log") return;
delete websocketData.t;
if (websocketData.init) {
let copy = [];
for (let d of websocketData.init) {
copy.push(d);
}
this.items = copy;
this.setFilter(this.filterString);
} else {
this.addItem(websocketData);
}
},
addItem(item) {
let copy = Object.assign({}, item);
this.items.push(copy);
if (this.filterString && this.filterPass(copy)) this.filtered.push(copy);
if (this.items.length > 1000) {
console.warn("Logbuffer too big. Pruning 800 items now");
this.items.splice(0, 800);
if (this.filterString) this.setFilter(this.filterString);
}
// isScrollBottom is a boolean prop which is true if the user is scrolled at the bottom before the new message is added
if (!this.$_scrollingToBottom && this.isScrollBottom) {
this.$_scrollingToBottom = true;
this.scrollToPosition(999999999);
console.log("scroll");
}
},
scrollDown(startIndex, endIndex, maxIndex) {
this.isScrollBottom = endIndex == maxIndex;
},
datetime(item) {
return this.dateTimeFormat.format(new Date(item.timestamp));
},
loglevelClass(item) {
switch (item.level) {
case "TRACE": return "as-console-trace";
case "INFO": return "as-console-info";
case "DEBUG": return "as-console-debug";
case "INFO": return "as-console-warn";
case "ERROR": return "as-console-error";
}
return "as-console-warn";
},
scrollToPosition(position) {
const scroller = this.$refs.scroller.$el;
scroller.scrollTop = position;
requestAnimationFrame(() => {
scroller.scrollTop = position;
setTimeout(() => {
scroller.scrollTop = position;
this.$_scrollingToBottom = false;
}, 50);
});
},
}
};
const mixins = [Mixin];
export { mixins };