|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- // Styles
- import '../../src/stylus/components/_overlay.styl';
- // Utilities
- import { keyCodes, addPassiveEventListener } from '../util/helpers';
- // Types
- import Vue from 'vue';
- /* @vue/component */
- export default Vue.extend().extend({
- name: 'overlayable',
- props: {
- hideOverlay: Boolean
- },
- data: function data() {
- return {
- overlay: null,
- overlayOffset: 0,
- overlayTimeout: undefined,
- overlayTransitionDuration: 500 + 150 // transition + delay
- };
- },
-
- watch: {
- hideOverlay: function hideOverlay(value) {
- if (value) this.removeOverlay();else this.genOverlay();
- }
- },
- beforeDestroy: function beforeDestroy() {
- this.removeOverlay();
- },
-
- methods: {
- genOverlay: function genOverlay() {
- var _this = this;
-
- // If fn is called and timeout is active
- // or overlay already exists
- // cancel removal of overlay and re-add active
- if (!this.isActive || this.hideOverlay || this.isActive && this.overlayTimeout || this.overlay) {
- clearTimeout(this.overlayTimeout);
- return this.overlay && this.overlay.classList.add('v-overlay--active');
- }
- this.overlay = document.createElement('div');
- this.overlay.className = 'v-overlay';
- if (this.absolute) this.overlay.className += ' v-overlay--absolute';
- this.hideScroll();
- var parent = this.absolute ? this.$el.parentNode : document.querySelector('[data-app]');
- parent && parent.insertBefore(this.overlay, parent.firstChild);
- // eslint-disable-next-line no-unused-expressions
- this.overlay.clientHeight; // Force repaint
- requestAnimationFrame(function () {
- // https://github.com/vuetifyjs/vuetify/issues/4678
- if (!_this.overlay) return;
- _this.overlay.className += ' v-overlay--active';
- if (_this.activeZIndex !== undefined) {
- _this.overlay.style.zIndex = String(_this.activeZIndex - 1);
- }
- });
- return true;
- },
-
- /** removeOverlay(false) will not restore the scollbar afterwards */
- removeOverlay: function removeOverlay() {
- var _this2 = this;
-
- var showScroll = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
-
- if (!this.overlay) {
- return showScroll && this.showScroll();
- }
- this.overlay.classList.remove('v-overlay--active');
- this.overlayTimeout = window.setTimeout(function () {
- // IE11 Fix
- try {
- if (_this2.overlay && _this2.overlay.parentNode) {
- _this2.overlay.parentNode.removeChild(_this2.overlay);
- }
- _this2.overlay = null;
- showScroll && _this2.showScroll();
- } catch (e) {
- console.log(e);
- }
- clearTimeout(_this2.overlayTimeout);
- _this2.overlayTimeout = undefined;
- }, this.overlayTransitionDuration);
- },
- scrollListener: function scrollListener(e) {
- if (e.type === 'keydown') {
- if (['INPUT', 'TEXTAREA', 'SELECT'].includes(e.target.tagName) ||
- // https://github.com/vuetifyjs/vuetify/issues/4715
- e.target.isContentEditable) return;
- var up = [keyCodes.up, keyCodes.pageup];
- var down = [keyCodes.down, keyCodes.pagedown];
- if (up.includes(e.keyCode)) {
- e.deltaY = -1;
- } else if (down.includes(e.keyCode)) {
- e.deltaY = 1;
- } else {
- return;
- }
- }
- if (e.target === this.overlay || e.type !== 'keydown' && e.target === document.body || this.checkPath(e)) e.preventDefault();
- },
- hasScrollbar: function hasScrollbar(el) {
- if (!el || el.nodeType !== Node.ELEMENT_NODE) return false;
- var style = window.getComputedStyle(el);
- return ['auto', 'scroll'].includes(style.overflowY) && el.scrollHeight > el.clientHeight;
- },
- shouldScroll: function shouldScroll(el, delta) {
- if (el.scrollTop === 0 && delta < 0) return true;
- return el.scrollTop + el.clientHeight === el.scrollHeight && delta > 0;
- },
- isInside: function isInside(el, parent) {
- if (el === parent) {
- return true;
- } else if (el === null || el === document.body) {
- return false;
- } else {
- return this.isInside(el.parentNode, parent);
- }
- },
- checkPath: function checkPath(e) {
- var path = e.path || this.composedPath(e);
- var delta = e.deltaY;
- if (e.type === 'keydown' && path[0] === document.body) {
- var dialog = this.$refs.dialog;
- var selected = window.getSelection().anchorNode;
- if (dialog && this.hasScrollbar(dialog) && this.isInside(selected, dialog)) {
- return this.shouldScroll(dialog, delta);
- }
- return true;
- }
- for (var index = 0; index < path.length; index++) {
- var el = path[index];
- if (el === document) return true;
- if (el === document.documentElement) return true;
- if (el === this.$refs.content) return true;
- if (this.hasScrollbar(el)) return this.shouldScroll(el, delta);
- }
- return true;
- },
-
- /**
- * Polyfill for Event.prototype.composedPath
- */
- composedPath: function composedPath(e) {
- if (e.composedPath) return e.composedPath();
- var path = [];
- var el = e.target;
- while (el) {
- path.push(el);
- if (el.tagName === 'HTML') {
- path.push(document);
- path.push(window);
- return path;
- }
- el = el.parentElement;
- }
- return path;
- },
- hideScroll: function hideScroll() {
- if (this.$vuetify.breakpoint.smAndDown) {
- document.documentElement.classList.add('overflow-y-hidden');
- } else {
- addPassiveEventListener(window, 'wheel', this.scrollListener, { passive: false });
- window.addEventListener('keydown', this.scrollListener);
- }
- },
- showScroll: function showScroll() {
- document.documentElement.classList.remove('overflow-y-hidden');
- window.removeEventListener('wheel', this.scrollListener);
- window.removeEventListener('keydown', this.scrollListener);
- }
- }
- });
- //# sourceMappingURL=overlayable.js.map
|