fixed bug $Modal

fixed bug $Modal
This commit is contained in:
梁灏 2016-11-16 20:48:58 +08:00
parent 381751c5d3
commit 2f71cf55cc
4 changed files with 1 additions and 441 deletions

View file

@ -1,169 +0,0 @@
import Vue from 'vue';
import Modal from './dialog.vue';
import Icon from '../icon/icon.vue';
import iButton from '../button/button.vue';
import { camelcaseToHyphen } from '../../utils/assist';
const prefixCls = 'ivu-modal-confirm';
Modal.newInstance = properties => {
const _props = properties || {};
let props = '';
Object.keys(_props).forEach(prop => {
props += ' :' + camelcaseToHyphen(prop) + '=' + prop;
});
const div = document.createElement('div');
div.innerHTML = `
<Modal${props} :visible.sync="visible" :width="width">
<div class="${prefixCls}">
<div class="${prefixCls}-head">
<div :class="iconTypeCls"><i :class="iconNameCls"></i></div>
<div class="${prefixCls}-head-title">{{{ title }}}</div>
</div>
<div class="${prefixCls}-body">
{{{ body }}}
</div>
<div class="${prefixCls}-footer">
<i-button type="ghost" size="large" v-if="showCancel" @click="cancel">{{ cancelText }}</i-button>
<i-button type="primary" size="large" :loading="buttonLoading" @click="ok">{{ okText }}</i-button>
</div>
</div>
</Modal>
`;
document.body.appendChild(div);
const modal = new Vue({
el: div,
components: { Modal, iButton, Icon },
data: Object.assign(_props, {
visible: false,
width: 416,
title: '',
body: '',
iconType: '',
iconName: '',
okText: '确定',
cancelText: '取消',
showCancel: false,
loading: false,
buttonLoading: false
}),
computed: {
iconTypeCls () {
return [
`${prefixCls}-head-icon`,
`${prefixCls}-head-icon-${this.iconType}`
]
},
iconNameCls () {
return [
'ivu-icon',
`ivu-icon-${this.iconName}`
]
}
},
methods: {
cancel () {
this.visible = false;
this.buttonLoading = false;
this.onCancel();
this.remove();
},
ok () {
if (this.loading) {
this.buttonLoading = true;
} else {
this.visible = false;
this.remove();
}
this.onOk();
},
remove () {
setTimeout(() => {
this.destroy();
}, 300);
},
destroy () {
this.$destroy();
document.body.removeChild(div);
this.onRemove();
},
onOk () {},
onCancel () {},
onRemove () {}
}
}).$children[0];
return {
show (props) {
modal.$parent.showCancel = props.showCancel;
modal.$parent.iconType = props.icon;
switch (props.icon) {
case 'info':
modal.$parent.iconName = 'information-circled';
break;
case 'success':
modal.$parent.iconName = 'checkmark-circled';
break;
case 'warning':
modal.$parent.iconName = 'android-alert';
break;
case 'error':
modal.$parent.iconName = 'close-circled';
break;
case 'confirm':
modal.$parent.iconName = 'help-circled';
break;
}
if ('width' in props) {
modal.$parent.width = props.width;
}
if ('title' in props) {
modal.$parent.title = props.title;
}
if ('content' in props) {
modal.$parent.body = props.content;
}
if ('okText' in props) {
modal.$parent.okText = props.okText;
}
if ('cancelText' in props) {
modal.$parent.cancelText = props.cancelText;
}
if ('onCancel' in props) {
modal.$parent.onCancel = props.onCancel;
}
if ('onOk' in props) {
modal.$parent.onOk = props.onOk;
}
// async for ok
if ('loading' in props) {
modal.$parent.loading = props.loading;
}
// notice when component destroy
modal.$parent.onRemove = props.onRemove;
modal.visible = true;
},
remove () {
modal.visible = false;
modal.$parent.buttonLoading = false;
modal.$parent.remove();
},
component: modal
}
};
export default Modal;

View file

@ -1,210 +0,0 @@
<template>
<div :class="wrapClasses">
<div :class="maskClasses" v-show="visible" @click="mask" transition="fade"></div>
<div :class="classes" :style="styles" v-show="visible" transition="ease">
<div :class="[prefixCls + '-content']">
<a :class="[prefixCls + '-close']" v-if="closable" @click="close">
<slot name="close">
<Icon type="ios-close-empty"></Icon>
</slot>
</a>
<div :class="[prefixCls + '-header']" v-if="showHead" v-el:head><slot name="header"><div :class="[prefixCls + '-header-inner']">{{ title }}</div></slot></div>
<div :class="[prefixCls + '-body']"><slot></slot></div>
<div :class="[prefixCls + '-footer']" v-if="!footerHide">
<slot name="footer">
<i-button type="ghost" size="large" @click="cancel">{{ cancelText }}</i-button>
<i-button type="primary" size="large" :loading="buttonLoading" @click="ok">{{ okText }}</i-button>
</slot>
</div>
</div>
</div>
</div>
</template>
<script>
import Icon from '../icon';
import iButton from '../button/button.vue';
import { getScrollBarSize } from '../../utils/assist';
const prefixCls = 'ivu-modal';
export default {
components: { Icon, iButton },
props: {
visible: {
type: Boolean,
default: false
},
closable: {
type: Boolean,
default: true
},
maskClosable: {
type: Boolean,
default: true
},
title: {
type: String
},
width: {
type: [Number, String],
default: 520
},
okText: {
type: String,
default: '确定'
},
cancelText: {
type: String,
default: '取消'
},
loading: {
type: Boolean,
default: false
},
style: {
type: Object
},
className: {
type: String
},
// for instance
footerHide: {
type: Boolean,
default: false
}
},
data () {
return {
prefixCls: prefixCls,
wrapShow: false,
showHead: true,
buttonLoading: false
}
},
computed: {
wrapClasses () {
return [
`${prefixCls}-wrap`,
{
[`${prefixCls}-hidden`]: !this.wrapShow,
[`${this.className}`]: !!this.className
}
]
},
maskClasses () {
return `${prefixCls}-mask`;
},
classes () {
return `${prefixCls}`;
},
styles () {
let style = {};
const styleWidth = {
width: `${this.width}px`
};
const customStyle = !!this.style ? this.style : {};
Object.assign(style, styleWidth, customStyle);
return style;
}
},
methods: {
close () {
this.visible = false;
this.$emit('on-cancel');
},
mask () {
if (this.maskClosable) {
this.close();
}
},
cancel () {
this.close();
},
ok () {
if (this.loading) {
this.buttonLoading = true;
} else {
this.visible = false;
}
this.$emit('on-ok');
},
EscClose (e) {
if (this.visible && this.closable) {
if (e.keyCode === 27) {
this.close()
}
}
},
checkScrollBar () {
let fullWindowWidth = window.innerWidth;
if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
const documentElementRect = document.documentElement.getBoundingClientRect();
fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left);
}
this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth;
if (this.bodyIsOverflowing) {
this.scrollBarWidth = getScrollBarSize();
}
},
setScrollBar () {
if (this.bodyIsOverflowing && this.scrollBarWidth !== undefined) {
document.body.style.paddingRight = `${this.scrollBarWidth}px`;
}
},
resetScrollBar () {
document.body.style.paddingRight = '';
},
addScrollEffect () {
this.checkScrollBar();
this.setScrollBar();
document.body.style.overflow = 'hidden';
},
removeScrollEffect() {
document.body.style.overflow = '';
this.resetScrollBar();
}
},
ready () {
if (this.visible) {
this.wrapShow = true;
}
let showHead = true;
if (this.$els.head.innerHTML == `<div class="${prefixCls}-header-inner"></div>` && !this.title) {
showHead = false;
}
this.showHead = showHead;
// ESC close
document.addEventListener('keydown', this.EscClose);
},
beforeDestroy () {
document.removeEventListener('keydown', this.EscClose);
},
watch: {
visible (val) {
if (val === false) {
this.buttonLoading = false;
setTimeout(() => {
this.wrapShow = false;
}, 300);
this.removeScrollEffect();
} else {
this.wrapShow = true;
this.addScrollEffect();
}
},
loading (val) {
if (!val) {
this.buttonLoading = false;
}
}
}
}
</script>

View file

@ -1,60 +0,0 @@
import Modal from './confirm';
let modalInstance;
function getModalInstance () {
modalInstance = modalInstance || Modal.newInstance({
closable: false,
maskClosable: false,
footerHide: true
});
return modalInstance;
}
function confirm (options) {
let instance = getModalInstance();
options.onRemove = function () {
modalInstance = null;
};
instance.show(options);
}
export default {
info (props = {}) {
props.icon = 'info';
props.showCancel = false;
return confirm(props);
},
success (props = {}) {
props.icon = 'success';
props.showCancel = false;
return confirm(props);
},
warning (props = {}) {
props.icon = 'warning';
props.showCancel = false;
return confirm(props);
},
error (props = {}) {
props.icon = 'error';
props.showCancel = false;
return confirm(props);
},
confirm (props = {}) {
props.icon = 'confirm';
props.showCancel = true;
return confirm(props);
},
remove () {
if (!modalInstance) { // at loading status, remove after Cancel
return false;
}
const instance = getModalInstance();
instance.remove();
}
}

View file

@ -9,7 +9,6 @@ import Cascader from './components/cascader';
import Checkbox from './components/checkbox';
import Circle from './components/circle';
import Collapse from './components/collapse';
import Dialog from './components/dialog';
import Icon from './components/icon';
import Input from './components/input';
import InputNumber from './components/input-number';
@ -82,7 +81,7 @@ const install = function (Vue) {
Vue.prototype.$Loading = LoadingBar;
Vue.prototype.$Message = Message;
Vue.prototype.$Modal = Dialog;
Vue.prototype.$Modal = Modal;
Vue.prototype.$Notice = Notice;
};