diff --git a/.gitignore b/.gitignore index 3663b35c7..60318e1ad 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ selenium-debug.log .idea/ *.gz dist-docs/ +dist/ diff --git a/.travis.yml b/.travis.yml index e4adad6b8..d809f5890 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,8 +11,6 @@ script: - npm run lint - npm run test - npm run dist - - npm run build -after_success: 'npm run coveralls' deploy: - provider: npm @@ -28,10 +26,3 @@ deploy: skip_cleanup: true on: tags: true - - provider: pages - verbose: true - skip_cleanup: true - github_token: $GITHUB_TOKEN - local_dir: dist-docs - on: - branch: master diff --git a/package.json b/package.json index e06ce2618..d6a48c3ba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "uiv", - "version": "0.36.0", + "version": "0.37.0", "description": "Bootstrap 3 components implemented by Vue 2.", "author": "wxsm", "main": "dist/uiv.common.js", diff --git a/src/components/modal/Modal.vue b/src/components/modal/Modal.vue index 3530fc6b0..448580bc5 100644 --- a/src/components/modal/Modal.vue +++ b/src/components/modal/Modal.vue @@ -49,14 +49,13 @@ toggleBodyOverflow, addClass, removeClass, - getComputedStyle + getComputedStyle, + getOpenModalNum, + getOpenModals } from '../../utils/domUtils' import { isFunction, isPromiseSupported } from '../../utils/objectUtils' - const MODAL_BACKDROP = 'modal-backdrop' const IN = 'in' - const getOpenModals = () => document.querySelectorAll(`.${MODAL_BACKDROP}`) - const getOpenModalNum = () => getOpenModals().length export default { mixins: [Local], @@ -210,37 +209,43 @@ const backdrop = this.$refs.backdrop clearTimeout(this.timeoutId) if (show) { - const alreadyOpenModalNum = getOpenModalNum() - document.body.appendChild(backdrop) - if (this.appendToBody) { - document.body.appendChild(modal) - } - modal.style.display = this.displayStyle - modal.scrollTop = 0 - backdrop.offsetHeight // force repaint - toggleBodyOverflow(false) - addClass(backdrop, IN) - addClass(modal, IN) - // fix z-index for nested modals - // no need to calculate if no modal is already open - if (alreadyOpenModalNum > 0) { - const modalBaseZ = parseInt(getComputedStyle(modal).zIndex) || 1050 // 1050 is default modal z-Index - const backdropBaseZ = parseInt(getComputedStyle(backdrop).zIndex) || 1040 // 1040 is default backdrop z-Index - const offset = alreadyOpenModalNum * this.zOffset - modal.style.zIndex = `${modalBaseZ + offset}` - backdrop.style.zIndex = `${backdropBaseZ + offset}` - } - // z-index fix end - this.timeoutId = setTimeout(() => { - if (this.autoFocus) { - let btn = this.$el.querySelector('[data-action="auto-focus"]') - if (btn) { - btn.focus() - } + // If two modals share the same v-if condition the calculated z-index is incorrect, + // resulting in popover misbehaviour. + // solved by adding a nextTick. + // https://github.com/uiv-lib/uiv/issues/342 + this.$nextTick(() => { + const alreadyOpenModalNum = getOpenModalNum() + document.body.appendChild(backdrop) + if (this.appendToBody) { + document.body.appendChild(modal) } - this.$emit('show') - this.timeoutId = 0 - }, this.transitionDuration) + modal.style.display = this.displayStyle + modal.scrollTop = 0 + backdrop.offsetHeight // force repaint + toggleBodyOverflow(false) + addClass(backdrop, IN) + addClass(modal, IN) + // fix z-index for nested modals + // no need to calculate if no modal is already open + if (alreadyOpenModalNum > 0) { + const modalBaseZ = parseInt(getComputedStyle(modal).zIndex) || 1050 // 1050 is default modal z-Index + const backdropBaseZ = parseInt(getComputedStyle(backdrop).zIndex) || 1040 // 1040 is default backdrop z-Index + const offset = alreadyOpenModalNum * this.zOffset + modal.style.zIndex = `${modalBaseZ + offset}` + backdrop.style.zIndex = `${backdropBaseZ + offset}` + } + // z-index fix end + this.timeoutId = setTimeout(() => { + if (this.autoFocus) { + let btn = this.$el.querySelector('[data-action="auto-focus"]') + if (btn) { + btn.focus() + } + } + this.$emit('show') + this.timeoutId = 0 + }, this.transitionDuration) + }) } else { removeClass(backdrop, IN) removeClass(modal, IN) diff --git a/src/components/select/MultiSelect.vue b/src/components/select/MultiSelect.vue index d45d421b9..bd2ce7f05 100644 --- a/src/components/select/MultiSelect.vue +++ b/src/components/select/MultiSelect.vue @@ -37,6 +37,7 @@ type="text" :placeholder="filterPlaceholder || t('uiv.multiSelect.filterPlaceholder')" v-model="filterInput" + @keyup.enter="searchClicked" @keydown.prevent.stop.down="goNextOption" @keydown.prevent.stop.up="goPrevOption" @keydown.prevent.stop.enter="selectOption" @@ -53,12 +54,16 @@ @click.stop="toggle(_item)" @mouseenter="currentActive=-1" style="outline: 0"> - - {{_item[labelKey]}} + + + + + + {{ _item[labelKey] }} - {{_item[labelKey]}} + {{ _item[labelKey] }} @@ -74,7 +79,7 @@ export default { mixins: [Local], - components: {Dropdown}, + components: { Dropdown }, props: { value: { type: Array, @@ -172,16 +177,8 @@ $group: v })) }, - flatternGroupedOptions () { - if (this.groupedOptions && this.groupedOptions.length) { - let result = [] - this.groupedOptions.forEach(v => { - result = result.concat(v.options) - }) - return result - } else { - return [] - } + flattenGroupedOptions () { + return [].concat(...this.groupedOptions.map(v => v.options)) }, selectClasses () { return { @@ -219,6 +216,9 @@ } else { return this.placeholder || this.t('uiv.multiSelect.placeholder') } + }, + customOptionsVisible () { + return !!this.$slots['option'] || !!this.$scopedSlots['option'] } }, watch: { @@ -242,17 +242,17 @@ if (!this.showDropdown) { return } - this.currentActive > 0 ? this.currentActive-- : this.currentActive = this.flatternGroupedOptions.length - 1 + this.currentActive > 0 ? this.currentActive-- : this.currentActive = this.flattenGroupedOptions.length - 1 }, goNextOption () { if (!this.showDropdown) { return } - this.currentActive < this.flatternGroupedOptions.length - 1 ? this.currentActive++ : this.currentActive = 0 + this.currentActive < this.flattenGroupedOptions.length - 1 ? this.currentActive++ : this.currentActive = 0 }, selectOption () { const index = this.currentActive - const options = this.flatternGroupedOptions + const options = this.flattenGroupedOptions if (!this.showDropdown) { this.showDropdown = true } else if (index >= 0 && index < options.length) { @@ -262,7 +262,7 @@ itemClasses (item) { const result = { disabled: item.disabled, - active: this.currentActive === this.flatternGroupedOptions.indexOf(item) + active: this.currentActive === this.flattenGroupedOptions.indexOf(item) } if (this.itemSelectedClass) { result[this.itemSelectedClass] = this.isItemSelected(item) @@ -297,6 +297,9 @@ this.$emit('limit-exceed') } } + }, + searchClicked () { + this.$emit('search', this.filterInput) } } } diff --git a/src/mixins/popupMixin.js b/src/mixins/popupMixin.js index fe7738286..043593b24 100644 --- a/src/mixins/popupMixin.js +++ b/src/mixins/popupMixin.js @@ -10,7 +10,8 @@ import { hasClass, setTooltipPosition, isElement, - addClass + addClass, + getOpenModalNum } from '../utils/domUtils' import {isString, isFunction} from '../utils/objectUtils' @@ -230,6 +231,12 @@ export default { this.showTimeoutId = 0 const popup = this.$refs.popup if (popup) { + const alreadyOpenModalNum = getOpenModalNum() + if (alreadyOpenModalNum > 1) { + const defaultZ = this.name === 'popover' ? 1060 : 1070 + const offset = (alreadyOpenModalNum - 1) * 20 + popup.style.zIndex = `${defaultZ + offset}` + } // add to dom if (!popUpAppendedContainer) { popup.className = `${this.name} ${this.placement} ${this.customClass ? this.customClass : ''} fade` diff --git a/src/utils/domUtils.js b/src/utils/domUtils.js index 46b104c15..47b3daf67 100644 --- a/src/utils/domUtils.js +++ b/src/utils/domUtils.js @@ -375,3 +375,13 @@ export function focus (el) { el.getAttribute('tabindex') ? null : el.setAttribute('tabindex', '-1') el.focus() } + +const MODAL_BACKDROP = 'modal-backdrop' + +export function getOpenModals () { + return document.querySelectorAll(`.${MODAL_BACKDROP}`) +} + +export function getOpenModalNum () { + return getOpenModals().length +}