// Mixins import Bootable from '../bootable'; // Utilities import { getObjectValueByPath } from '../../util/helpers'; import mixins from '../../util/mixins'; import { consoleWarn } from '../../util/console'; function validateAttachTarget(val) { const type = typeof val; if (type === 'boolean' || type === 'string') return true; return val.nodeType === Node.ELEMENT_NODE; } /* @vue/component */ export default mixins(Bootable).extend({ name: 'detachable', props: { attach: { default: false, validator: validateAttachTarget }, contentClass: { type: String, default: '' } }, data: () => ({ activatorNode: null, hasDetached: false }), watch: { attach() { this.hasDetached = false; this.initDetach(); }, hasContent: 'initDetach' }, beforeMount() { this.$nextTick(() => { if (this.activatorNode) { const activator = Array.isArray(this.activatorNode) ? this.activatorNode : [this.activatorNode]; activator.forEach(node => { if (!node.elm) return; if (!this.$el.parentNode) return; const target = this.$el === this.$el.parentNode.firstChild ? this.$el : this.$el.nextSibling; this.$el.parentNode.insertBefore(node.elm, target); }); } }); }, mounted() { this.eager && this.initDetach(); }, deactivated() { this.isActive = false; }, beforeDestroy() { // IE11 Fix try { if (this.$refs.content && this.$refs.content.parentNode) { this.$refs.content.parentNode.removeChild(this.$refs.content); } if (this.activatorNode) { const activator = Array.isArray(this.activatorNode) ? this.activatorNode : [this.activatorNode]; activator.forEach(node => { node.elm && node.elm.parentNode && node.elm.parentNode.removeChild(node.elm); }); } } catch (e) { console.log(e); } }, methods: { getScopeIdAttrs() { const scopeId = getObjectValueByPath(this.$vnode, 'context.$options._scopeId'); return scopeId && { [scopeId]: '' }; }, initDetach() { if (this._isDestroyed || !this.$refs.content || this.hasDetached || // Leave menu in place if attached // and dev has not changed target this.attach === '' || // If used as a boolean prop () this.attach === true || // If bound to a boolean () this.attach === 'attach' // If bound as boolean prop in pug (v-menu(attach)) ) return; let target; if (this.attach === false) { // Default, detach to app target = document.querySelector('[data-app]'); } else if (typeof this.attach === 'string') { // CSS selector target = document.querySelector(this.attach); } else { // DOM Element target = this.attach; } if (!target) { consoleWarn(`Unable to locate target ${this.attach || '[data-app]'}`, this); return; } target.insertBefore(this.$refs.content, target.firstChild); this.hasDetached = true; } } }); //# sourceMappingURL=index.js.map