diff --git a/src/components/Select.vue b/src/components/Select.vue index 0f81b6b68..c5f801f0b 100644 --- a/src/components/Select.vue +++ b/src/components/Select.vue @@ -88,7 +88,7 @@ :id="`vs${uid}__listbox`" ref="dropdownMenu" :key="`vs${uid}__listbox`" - v-append-to-body + v-append-to class="vs__dropdown-menu" role="listbox" tabindex="-1" @@ -140,7 +140,7 @@ import pointerScroll from '@/mixins/pointerScroll.js' import typeAheadPointer from '@/mixins/typeAheadPointer.js' import ajax from '@/mixins/ajax.js' import childComponents from '@/components/childComponents.js' -import appendToBody from '@/directives/appendToBody.js' +import appendTo from '@/directives/appendTo.js' import sortAndStringify from '@/utility/sortAndStringify.js' import uniqueId from '@/utility/uniqueId.js' @@ -150,7 +150,7 @@ import uniqueId from '@/utility/uniqueId.js' export default { components: { ...childComponents }, - directives: { appendToBody }, + directives: { appendTo }, mixins: [pointerScroll, typeAheadPointer, ajax], @@ -627,18 +627,17 @@ export default { }, /** - * Append the dropdown element to the end of the body + * Append the dropdown element to the specified element (or its DOM selector) * and size/position it dynamically. Use it if you have * overflow or z-index issues. - * @type {Boolean} + * Note: the specified element must already exist (be mounted) in the DOM. */ - appendToBody: { - type: Boolean, + appendTo: { default: false, }, /** - * When `appendToBody` is true, this function is responsible for + * When `appendTo` is not false, this function is responsible for * positioning the drop down list. * * If a function is returned from `calculatePosition`, it will diff --git a/src/directives/appendTo.js b/src/directives/appendTo.js new file mode 100644 index 000000000..74818b75a --- /dev/null +++ b/src/directives/appendTo.js @@ -0,0 +1,36 @@ +export default { + mounted(el, { instance }) { + if (instance.appendTo) { + const { + height, + top, + left, + width, + } = instance.$refs.toggle.getBoundingClientRect() + const relEl = instance.appendTo instanceof Element ? instance.appendTo : document.querySelector(instance.appendTo) + if (relEl instanceof Element) { + const isBody = relEl === document.body + const scrollX = isBody ? (window.scrollX || window.pageXOffset) : 0 + const scrollY = isBody ? (window.scrollY || window.pageYOffset) : 0 + const relRect = relEl.getBoundingClientRect() + el.unbindPosition = instance.calculatePosition(el, instance, { + width: width + 'px', + left: scrollX + left - relRect.left + 'px', + top: scrollY + top - relRect.top + height + 'px' + }) + relEl.appendChild(el) + } + } + }, + + unmounted(el, { instance }) { + if (instance.appendTo) { + if (el.unbindPosition && typeof el.unbindPosition === 'function') { + el.unbindPosition() + } + if (el.parentNode) { + el.parentNode.removeChild(el) + } + } + }, +} diff --git a/src/directives/appendToBody.js b/src/directives/appendToBody.js deleted file mode 100644 index 514e1446b..000000000 --- a/src/directives/appendToBody.js +++ /dev/null @@ -1,32 +0,0 @@ -export default { - mounted(el, { instance }) { - if (instance.appendToBody) { - const { - height, - top, - left, - width, - } = instance.$refs.toggle.getBoundingClientRect() - let scrollX = window.scrollX || window.pageXOffset - let scrollY = window.scrollY || window.pageYOffset - el.unbindPosition = instance.calculatePosition(el, instance, { - width: width + 'px', - left: scrollX + left + 'px', - top: scrollY + top + height + 'px', - }) - - document.body.appendChild(el) - } - }, - - unmounted(el, { instance }) { - if (instance.appendToBody) { - if (el.unbindPosition && typeof el.unbindPosition === 'function') { - el.unbindPosition() - } - if (el.parentNode) { - el.parentNode.removeChild(el) - } - } - }, -}