UNPKG

vuikit

Version:

A responsive Vue UI library for web site interfaces based on UIkit

239 lines (233 loc) 6.82 kB
/** * Vuikit 0.8.10 * (c) 2018 Miljan Aleksic * @license MIT **/ /* Substantial part of the code is adapted from UIkit, Copyright (c) 2013-2018 YOOtheme GmbH, getuikit.com */ import { $$, $ } from './util/core'; import { css } from './util/style'; import { data } from './util/attr'; import { warn } from './util/debug'; import { filter } from './util/filter'; import { trigger } from './util/event'; import { isInView, height, offset } from './util/dimensions'; import { filterOutTextNodes } from './util/vue'; import { addClass, removeClass, toggleClass } from './util/class'; import MixinEvents from './mixins/events'; import MixinFastdom from './mixins/fastdom'; import { closest } from './util/selector'; var scrollspy = { name: 'VkScrollspy', abstract: true, mixins: [MixinEvents, MixinFastdom], props: { cls: { type: Array, default: function () { return []; } }, target: { default: false }, hidden: { type: Boolean, default: true }, offsetTop: { type: Number, default: 0 }, offsetLeft: { type: Number, default: 0 }, repeat: { type: Boolean, default: false }, delay: { type: Number, default: 0 } }, classMapping: { inViewClass: 'uk-scrollspy-inview' }, computed: { elements: function elements () { return this.target ? $$(this.target, this.$el) : [ this.$el ] } }, fastdom: [ { write: function write () { var ref = this.$options.classMapping; var inViewClass = ref.inViewClass; if (this.hidden) { css(filter(this.elements, (":not(." + inViewClass + ")")), 'visibility', 'hidden'); } } }, { read: function read (els) { var this$1 = this; this.elements.forEach(function (el, i) { var elData = els[i]; if (!elData || elData.el !== el) { var cls = data(el, 'vk-scrollspy-class'); elData = {el: el, toggles: cls && cls.split(',') || this$1.cls}; } elData.show = isInView(el, this$1.offsetTop, this$1.offsetLeft); els[i] = elData; }); }, write: function write (els) { var this$1 = this; var ref = this.$options.classMapping; var inViewClass = ref.inViewClass; var index = this.elements.length === 1 ? 1 : 0; this.elements.forEach(function (el, i) { var elData = els[i]; var cls = elData.toggles[i] || elData.toggles[0]; if (elData.show && !elData.inview && !elData.timer) { var show = function () { css(el, 'visibility', ''); addClass(el, inViewClass); toggleClass(el, cls); trigger(el, 'inview'); this$1.fastdomUpdate(); elData.inview = true; delete elData.timer; }; if (this$1.delay && index) { elData.timer = setTimeout(show, this$1.delay * index); } else { show(); } index++; } else if (!elData.show && elData.inview && this$1.repeat) { if (elData.timer) { clearTimeout(elData.timer); delete elData.timer; } css(el, 'visibility', this$1.hidden ? 'hidden' : ''); removeClass(el, inViewClass); toggleClass(el, cls); trigger(el, 'outview'); this$1.fastdomUpdate(); elData.inview = false; } }); }, events: ['scroll', 'load', 'resize'] } ], render: function render (h) { var children = this.$slots.default; if (!children) { return } children = filterOutTextNodes(children); if (!children.length) { return } if (process.env.NODE_ENV !== 'production' && children.length > 1) { warn('vk-scrollspy can only be used on a single element', this.$parent); } return children[0] } } var scrollspyNav = { name: 'VkScrollspyNav', abstract: true, mixins: [MixinEvents, MixinFastdom], props: { cls: { type: String, default: 'uk-active' }, closest: { type: String, default: '' }, overflow: { type: Boolean, default: true }, offset: { type: Number, default: 0 } }, methods: { setComputed: function setComputed () { this.links = $$('a[href^="#"]', this.$el).filter(function (el) { return el.hash; }); this.elements = this.closest ? closest(this.links, this.closest) : this.links; this.targets = $$(this.links.map(function (el) { return el.hash; }).join(',')); } }, fastdom: [ { read: function read (data$$1) { var this$1 = this; var scroll = window.pageYOffset + this.offset + 1; var max = height(document) - height(window) + this.offset; data$$1.active = false; this.targets.every(function (el, i) { var ref = offset(el); var top = ref.top; var last = i + 1 === this$1.targets.length; if (!this$1.overflow && (i === 0 && top > scroll || last && top + el.offsetTop < scroll)) { return false } if (!last && offset(this$1.targets[i + 1]).top <= scroll) { return true } if (scroll >= max) { for (var j = this$1.targets.length - 1; j > i; j--) { if (isInView(this$1.targets[j])) { el = this$1.targets[j]; break } } } return !(data$$1.active = $(filter(this$1.links, ("[href=\"#" + (el.id) + "\"]")))) }); }, write: function write (ref) { var active = ref.active; this.links.forEach(function (el) { return el.blur(); }); removeClass(this.elements, this.cls); if (active) { trigger(this.$el, 'active', [active, addClass(this.closest ? closest(active, this.closest) : active, this.cls)]); } }, events: ['scroll', 'load', 'resize'] } ], mounted: function mounted () { this.setComputed(); }, updated: function updated () { var this$1 = this; this.$nextTick(function () { this$1.setComputed(); this$1.fastdomUpdate(); }); }, render: function render (h) { var children = this.$slots.default; if (!children) { return } children = filterOutTextNodes(children); if (!children.length) { return } if (process.env.NODE_ENV !== 'production' && children.length > 1) { warn('vk-scrollspy can only be used on a single element', this.$parent); } return children[0] } } export { scrollspy as Scrollspy, scrollspyNav as ScrollspyNav };