first
This commit is contained in:
14
packages/popover/index.js
Normal file
14
packages/popover/index.js
Normal file
@ -0,0 +1,14 @@
|
||||
import Popover from './src/main';
|
||||
import directive from './src/directive';
|
||||
import Vue from 'vue';
|
||||
|
||||
Vue.directive('popover', directive);
|
||||
|
||||
/* istanbul ignore next */
|
||||
Popover.install = function(Vue) {
|
||||
Vue.directive('popover', directive);
|
||||
Vue.component(Popover.name, Popover);
|
||||
};
|
||||
Popover.directive = directive;
|
||||
|
||||
export default Popover;
|
20
packages/popover/src/directive.js
Normal file
20
packages/popover/src/directive.js
Normal file
@ -0,0 +1,20 @@
|
||||
const getReference = (el, binding, vnode) => {
|
||||
const _ref = binding.expression ? binding.value : binding.arg;
|
||||
const popper = vnode.context.$refs[_ref];
|
||||
if (popper) {
|
||||
if (Array.isArray(popper)) {
|
||||
popper[0].$refs.reference = el;
|
||||
} else {
|
||||
popper.$refs.reference = el;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
bind(el, binding, vnode) {
|
||||
getReference(el, binding, vnode);
|
||||
},
|
||||
inserted(el, binding, vnode) {
|
||||
getReference(el, binding, vnode);
|
||||
}
|
||||
};
|
237
packages/popover/src/main.vue
Normal file
237
packages/popover/src/main.vue
Normal file
@ -0,0 +1,237 @@
|
||||
<template>
|
||||
<span>
|
||||
<transition
|
||||
:name="transition"
|
||||
@after-enter="handleAfterEnter"
|
||||
@after-leave="handleAfterLeave">
|
||||
<div
|
||||
class="el-popover el-popper"
|
||||
:class="[popperClass, content && 'el-popover--plain']"
|
||||
ref="popper"
|
||||
v-show="!disabled && showPopper"
|
||||
:style="{ width: width + 'px' }"
|
||||
role="tooltip"
|
||||
:id="tooltipId"
|
||||
:aria-hidden="(disabled || !showPopper) ? 'true' : 'false'"
|
||||
>
|
||||
<div class="el-popover__title" v-if="title" v-text="title"></div>
|
||||
<slot>{{ content }}</slot>
|
||||
</div>
|
||||
</transition>
|
||||
<span class="el-popover__reference-wrapper" ref="wrapper" >
|
||||
<slot name="reference"></slot>
|
||||
</span>
|
||||
</span>
|
||||
</template>
|
||||
<script>
|
||||
import Popper from 'element-ui/src/utils/vue-popper';
|
||||
import { on, off } from 'element-ui/src/utils/dom';
|
||||
import { addClass, removeClass } from 'element-ui/src/utils/dom';
|
||||
import { generateId } from 'element-ui/src/utils/util';
|
||||
|
||||
export default {
|
||||
name: 'ElPopover',
|
||||
|
||||
mixins: [Popper],
|
||||
|
||||
props: {
|
||||
trigger: {
|
||||
type: String,
|
||||
default: 'click',
|
||||
validator: value => ['click', 'focus', 'hover', 'manual'].indexOf(value) > -1
|
||||
},
|
||||
openDelay: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
closeDelay: {
|
||||
type: Number,
|
||||
default: 200
|
||||
},
|
||||
title: String,
|
||||
disabled: Boolean,
|
||||
content: String,
|
||||
reference: {},
|
||||
popperClass: String,
|
||||
width: {},
|
||||
visibleArrow: {
|
||||
default: true
|
||||
},
|
||||
arrowOffset: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
transition: {
|
||||
type: String,
|
||||
default: 'fade-in-linear'
|
||||
},
|
||||
tabindex: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
tooltipId() {
|
||||
return `el-popover-${generateId()}`;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
showPopper(val) {
|
||||
if (this.disabled) {
|
||||
return;
|
||||
}
|
||||
val ? this.$emit('show') : this.$emit('hide');
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
let reference = this.referenceElm = this.reference || this.$refs.reference;
|
||||
const popper = this.popper || this.$refs.popper;
|
||||
|
||||
if (!reference && this.$refs.wrapper.children) {
|
||||
reference = this.referenceElm = this.$refs.wrapper.children[0];
|
||||
}
|
||||
// 可访问性
|
||||
if (reference) {
|
||||
addClass(reference, 'el-popover__reference');
|
||||
reference.setAttribute('aria-describedby', this.tooltipId);
|
||||
reference.setAttribute('tabindex', this.tabindex); // tab序列
|
||||
popper.setAttribute('tabindex', 0);
|
||||
|
||||
if (this.trigger !== 'click') {
|
||||
on(reference, 'focusin', () => {
|
||||
this.handleFocus();
|
||||
const instance = reference.__vue__;
|
||||
if (instance && typeof instance.focus === 'function') {
|
||||
instance.focus();
|
||||
}
|
||||
});
|
||||
on(popper, 'focusin', this.handleFocus);
|
||||
on(reference, 'focusout', this.handleBlur);
|
||||
on(popper, 'focusout', this.handleBlur);
|
||||
}
|
||||
on(reference, 'keydown', this.handleKeydown);
|
||||
on(reference, 'click', this.handleClick);
|
||||
}
|
||||
if (this.trigger === 'click') {
|
||||
on(reference, 'click', this.doToggle);
|
||||
on(document, 'click', this.handleDocumentClick);
|
||||
} else if (this.trigger === 'hover') {
|
||||
on(reference, 'mouseenter', this.handleMouseEnter);
|
||||
on(popper, 'mouseenter', this.handleMouseEnter);
|
||||
on(reference, 'mouseleave', this.handleMouseLeave);
|
||||
on(popper, 'mouseleave', this.handleMouseLeave);
|
||||
} else if (this.trigger === 'focus') {
|
||||
if (this.tabindex < 0) {
|
||||
console.warn('[Element Warn][Popover]a negative taindex means that the element cannot be focused by tab key');
|
||||
}
|
||||
if (reference.querySelector('input, textarea')) {
|
||||
on(reference, 'focusin', this.doShow);
|
||||
on(reference, 'focusout', this.doClose);
|
||||
} else {
|
||||
on(reference, 'mousedown', this.doShow);
|
||||
on(reference, 'mouseup', this.doClose);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.cleanup();
|
||||
},
|
||||
|
||||
deactivated() {
|
||||
this.cleanup();
|
||||
},
|
||||
|
||||
methods: {
|
||||
doToggle() {
|
||||
this.showPopper = !this.showPopper;
|
||||
},
|
||||
doShow() {
|
||||
this.showPopper = true;
|
||||
},
|
||||
doClose() {
|
||||
this.showPopper = false;
|
||||
},
|
||||
handleFocus() {
|
||||
addClass(this.referenceElm, 'focusing');
|
||||
if (this.trigger === 'click' || this.trigger === 'focus') this.showPopper = true;
|
||||
},
|
||||
handleClick() {
|
||||
removeClass(this.referenceElm, 'focusing');
|
||||
},
|
||||
handleBlur() {
|
||||
removeClass(this.referenceElm, 'focusing');
|
||||
if (this.trigger === 'click' || this.trigger === 'focus') this.showPopper = false;
|
||||
},
|
||||
handleMouseEnter() {
|
||||
clearTimeout(this._timer);
|
||||
if (this.openDelay) {
|
||||
this._timer = setTimeout(() => {
|
||||
this.showPopper = true;
|
||||
}, this.openDelay);
|
||||
} else {
|
||||
this.showPopper = true;
|
||||
}
|
||||
},
|
||||
handleKeydown(ev) {
|
||||
if (ev.keyCode === 27 && this.trigger !== 'manual') { // esc
|
||||
this.doClose();
|
||||
}
|
||||
},
|
||||
handleMouseLeave() {
|
||||
clearTimeout(this._timer);
|
||||
if (this.closeDelay) {
|
||||
this._timer = setTimeout(() => {
|
||||
this.showPopper = false;
|
||||
}, this.closeDelay);
|
||||
} else {
|
||||
this.showPopper = false;
|
||||
}
|
||||
},
|
||||
handleDocumentClick(e) {
|
||||
let reference = this.reference || this.$refs.reference;
|
||||
const popper = this.popper || this.$refs.popper;
|
||||
|
||||
if (!reference && this.$refs.wrapper.children) {
|
||||
reference = this.referenceElm = this.$refs.wrapper.children[0];
|
||||
}
|
||||
if (!this.$el ||
|
||||
!reference ||
|
||||
this.$el.contains(e.target) ||
|
||||
reference.contains(e.target) ||
|
||||
!popper ||
|
||||
popper.contains(e.target)) return;
|
||||
this.showPopper = false;
|
||||
},
|
||||
handleAfterEnter() {
|
||||
this.$emit('after-enter');
|
||||
},
|
||||
handleAfterLeave() {
|
||||
this.$emit('after-leave');
|
||||
this.doDestroy();
|
||||
},
|
||||
cleanup() {
|
||||
if (this.openDelay || this.closeDelay) {
|
||||
clearTimeout(this._timer);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
destroyed() {
|
||||
const reference = this.reference;
|
||||
|
||||
off(reference, 'click', this.doToggle);
|
||||
off(reference, 'mouseup', this.doClose);
|
||||
off(reference, 'mousedown', this.doShow);
|
||||
off(reference, 'focusin', this.doShow);
|
||||
off(reference, 'focusout', this.doClose);
|
||||
off(reference, 'mousedown', this.doShow);
|
||||
off(reference, 'mouseup', this.doClose);
|
||||
off(reference, 'mouseleave', this.handleMouseLeave);
|
||||
off(reference, 'mouseenter', this.handleMouseEnter);
|
||||
off(document, 'click', this.handleDocumentClick);
|
||||
}
|
||||
};
|
||||
</script>
|
Reference in New Issue
Block a user