iview/src/components/poptip/poptip.vue

297 lines
11 KiB
Vue
Raw Normal View History

<template>
<div
:class="classes"
@mouseenter="handleMouseenter"
@mouseleave="handleMouseleave"
v-click-outside="handleClose">
<div
2016-10-28 17:24:52 +08:00
:class="[prefixCls + '-rel']"
ref="reference"
@click="handleClick"
@mousedown="handleFocus(false)"
@mouseup="handleBlur(false)">
<slot></slot>
</div>
<transition name="fade">
<div
2017-08-21 17:15:06 +08:00
:class="popperClasses"
:style="styles"
ref="popper"
v-show="visible"
2017-10-23 14:12:02 +08:00
@click="handleTransferClick"
@mouseenter="handleMouseenter"
@mouseleave="handleMouseleave"
:data-transfer="transfer"
v-transfer-dom>
<div :class="[prefixCls + '-content']">
<div :class="[prefixCls + '-arrow']"></div>
<div :class="[prefixCls + '-inner']" v-if="confirm">
<div :class="[prefixCls + '-body']">
2018-06-25 14:17:10 +08:00
<i class="ivu-icon ivu-icon-ios-help-circle"></i>
<div :class="[prefixCls + '-body-message']"><slot name="title">{{ title }}</slot></div>
</div>
<div :class="[prefixCls + '-footer']">
<i-button type="text" size="small" @click.native="cancel">{{ localeCancelText }}</i-button>
<i-button type="primary" size="small" @click.native="ok">{{ localeOkText }}</i-button>
</div>
</div>
<div :class="[prefixCls + '-inner']" v-if="!confirm">
2018-06-22 15:37:23 +08:00
<div :class="[prefixCls + '-title']" :style="contentPaddingStyle" v-if="showTitle" ref="title"><slot name="title"><div :class="[prefixCls + '-title-inner']">{{ title }}</div></slot></div>
<div :class="[prefixCls + '-body']" :style="contentPaddingStyle">
2018-06-22 15:32:04 +08:00
<div :class="contentClasses"><slot name="content"><div :class="[prefixCls + '-body-content-inner']">{{ content }}</div></slot></div>
</div>
2016-10-27 12:10:59 +08:00
</div>
</div>
</div>
</transition>
</div>
</template>
<script>
import Popper from '../base/popper';
2016-10-28 18:27:04 +08:00
import iButton from '../button/button.vue';
import {directive as clickOutside} from 'v-click-outside-x';
import TransferDom from '../../directives/transfer-dom';
import { oneOf } from '../../utils/assist';
2018-09-10 16:10:35 +08:00
import { transferIndex, transferIncrease } from '../../utils/transfer-queue';
import Locale from '../../mixins/locale';
const prefixCls = 'ivu-poptip';
export default {
name: 'Poptip',
mixins: [ Popper, Locale ],
directives: { clickOutside, TransferDom },
2016-10-28 18:27:04 +08:00
components: { iButton },
props: {
trigger: {
validator (value) {
return oneOf(value, ['click', 'focus', 'hover']);
},
default: 'click'
},
placement: {
validator (value) {
return oneOf(value, ['top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end', 'left', 'left-start', 'left-end', 'right', 'right-start', 'right-end']);
},
default: 'top'
},
title: {
type: [String, Number]
},
content: {
type: [String, Number],
default: ''
},
width: {
type: [String, Number]
},
confirm: {
type: Boolean,
default: false
},
okText: {
type: String
},
cancelText: {
type: String
},
transfer: {
type: Boolean,
2018-06-28 15:04:19 +08:00
default () {
2018-08-07 16:35:27 +08:00
return !this.$IVIEW || this.$IVIEW.transfer === '' ? false : this.$IVIEW.transfer;
2018-06-28 15:04:19 +08:00
}
},
popperClass: {
type: String
2018-06-22 15:32:04 +08:00
},
wordWrap: {
type: Boolean,
default: false
2018-06-22 15:37:23 +08:00
},
// default by css: 8px 16px
padding: {
type: String
}
},
data () {
return {
2016-10-27 11:24:13 +08:00
prefixCls: prefixCls,
showTitle: true,
2017-10-23 14:12:02 +08:00
isInput: false,
disableCloseUnderTransfer: false, // transfer 模式下,点击 slot 也会触发关闭
2018-09-10 16:10:35 +08:00
tIndex: this.handleGetIndex()
2016-12-25 22:49:42 +08:00
};
},
computed: {
classes () {
return [
2016-10-28 18:27:04 +08:00
`${prefixCls}`,
{
2016-10-28 18:27:04 +08:00
[`${prefixCls}-confirm`]: this.confirm
}
2016-12-25 22:49:42 +08:00
];
},
2017-08-21 17:15:06 +08:00
popperClasses () {
return [
`${prefixCls}-popper`,
{
[`${prefixCls}-confirm`]: this.transfer && this.confirm,
[`${this.popperClass}`]: !!this.popperClass
2017-08-21 17:15:06 +08:00
}
];
},
styles () {
let style = {};
2016-12-25 22:49:42 +08:00
if (this.width) {
2016-10-28 18:27:04 +08:00
style.width = `${this.width}px`;
}
2018-09-10 16:10:35 +08:00
if (this.transfer) style['z-index'] = 1060 + this.tIndex;
return style;
},
localeOkText () {
if (this.okText === undefined) {
return this.t('i.poptip.okText');
} else {
return this.okText;
}
},
localeCancelText () {
if (this.cancelText === undefined) {
return this.t('i.poptip.cancelText');
} else {
return this.cancelText;
}
2018-06-22 15:32:04 +08:00
},
contentClasses () {
return [
`${prefixCls}-body-content`,
{
[`${prefixCls}-body-content-word-wrap`]: this.wordWrap
}
];
2018-06-22 15:37:23 +08:00
},
contentPaddingStyle () {
const styles = {};
if (this.padding !== '') styles['padding'] = this.padding;
2018-06-22 15:37:23 +08:00
return styles;
2018-09-10 16:10:35 +08:00
},
},
methods: {
handleClick () {
if (this.confirm) {
this.visible = !this.visible;
return true;
}
if (this.trigger !== 'click') {
return false;
}
this.visible = !this.visible;
},
2017-10-23 14:12:02 +08:00
handleTransferClick () {
if (this.transfer) this.disableCloseUnderTransfer = true;
},
handleClose () {
2017-10-23 14:12:02 +08:00
if (this.disableCloseUnderTransfer) {
this.disableCloseUnderTransfer = false;
return false;
}
if (this.confirm) {
this.visible = false;
return true;
}
if (this.trigger !== 'click') {
return false;
}
this.visible = false;
},
handleFocus (fromInput = true) {
if (this.trigger !== 'focus' || this.confirm || (this.isInput && !fromInput)) {
return false;
}
this.visible = true;
},
handleBlur (fromInput = true) {
if (this.trigger !== 'focus' || this.confirm || (this.isInput && !fromInput)) {
return false;
}
this.visible = false;
},
handleMouseenter () {
if (this.trigger !== 'hover' || this.confirm) {
return false;
}
if (this.enterTimer) clearTimeout(this.enterTimer);
this.enterTimer = setTimeout(() => {
this.visible = true;
}, 100);
},
handleMouseleave () {
if (this.trigger !== 'hover' || this.confirm) {
return false;
}
if (this.enterTimer) {
clearTimeout(this.enterTimer);
this.enterTimer = setTimeout(() => {
this.visible = false;
}, 100);
}
},
cancel () {
this.visible = false;
this.$emit('on-cancel');
},
ok () {
this.visible = false;
this.$emit('on-ok');
},
getInputChildren () {
const $input = this.$refs.reference.querySelectorAll('input');
const $textarea = this.$refs.reference.querySelectorAll('textarea');
let $children = null;
if ($input.length) {
$children = $input[0];
} else if ($textarea.length) {
$children = $textarea[0];
}
return $children;
2018-09-10 16:10:35 +08:00
},
handleGetIndex () {
transferIncrease();
return transferIndex;
},
handleIndexIncrease () {
this.tIndex = this.handleGetIndex();
}
2016-10-27 11:24:13 +08:00
},
mounted () {
2016-10-27 11:24:13 +08:00
if (!this.confirm) {
// this.showTitle = this.$refs.title.innerHTML != `<div class="${prefixCls}-title-inner"></div>`;
2017-06-20 16:47:37 +08:00
this.showTitle = (this.$slots.title !== undefined) || this.title;
2016-10-27 11:24:13 +08:00
}
// if trigger and children is input or textarea,listen focus & blur event
if (this.trigger === 'focus') {
2017-06-07 16:31:57 +08:00
this.$nextTick(() => {
const $children = this.getInputChildren();
if ($children) {
2017-06-20 16:47:37 +08:00
this.isInput = true;
2017-06-07 16:31:57 +08:00
$children.addEventListener('focus', this.handleFocus, false);
$children.addEventListener('blur', this.handleBlur, false);
}
});
}
},
beforeDestroy () {
const $children = this.getInputChildren();
if ($children) {
$children.removeEventListener('focus', this.handleFocus, false);
$children.removeEventListener('blur', this.handleBlur, false);
}
}
2016-12-25 22:49:42 +08:00
};
2016-10-28 17:24:52 +08:00
</script>