Add vue-popup and dom helper

pull/1982/head
qingwei.li 2016-12-26 11:41:15 +08:00
parent daec90af9f
commit a906a5fccb
40 changed files with 706 additions and 54 deletions

View File

@ -1,5 +1,5 @@
<script> <script>
import { addClass } from 'wind-dom/src/class'; import { addClass } from 'element-ui/src/utils/dom';
export default { export default {
data() { data() {
return { return {
@ -78,7 +78,7 @@ Different colors represent different meanings.
``` ```
::: :::
### Icon Button ### Icon Button
Use icons to add more meaning to Button. You can use icon alone to save some space, or with text together. Use icons to add more meaning to Button. You can use icon alone to save some space, or with text together.

View File

@ -1,4 +1,4 @@
## Pagination ## Pagination
If you have too much data to display in one page, use pagination. If you have too much data to display in one page, use pagination.
@ -117,7 +117,7 @@ Add more modules based on your scenario.
``` ```
::: :::
<script> <script>
import { addClass } from 'wind-dom/src/class'; import { addClass } from 'element-ui/src/utils/dom';
export default { export default {
data() { data() {
return { return {

View File

@ -1,5 +1,5 @@
<script> <script>
import { addClass } from 'wind-dom/src/class'; import { addClass } from 'element-ui/src/utils/dom';
export default { export default {
data() { data() {
return { return {

View File

@ -117,7 +117,7 @@
``` ```
::: :::
<script> <script>
import { addClass } from 'wind-dom/src/class'; import { addClass } from 'element-ui/src/utils/dom';
export default { export default {
methods: { methods: {
handleSizeChange(val) { handleSizeChange(val) {

View File

@ -45,9 +45,7 @@
"async-validator": "^1.6.6", "async-validator": "^1.6.6",
"babel-helper-vue-jsx-merge-props": "^2.0.0", "babel-helper-vue-jsx-merge-props": "^2.0.0",
"deepmerge": "^1.2.0", "deepmerge": "^1.2.0",
"throttle-debounce": "^1.0.1", "throttle-debounce": "^1.0.1"
"vue-popup": "^0.2.14",
"wind-dom": "0.0.3"
}, },
"peerDependencies": { "peerDependencies": {
"vue": "^2.1.6" "vue": "^2.1.6"

View File

@ -12,6 +12,5 @@
"author": "long.zhang@ele.me", "author": "long.zhang@ele.me",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"wind-dom": "0.0.3"
} }
} }

View File

@ -32,7 +32,7 @@
<script> <script>
import { getFirstDayOfMonth, getDayCountOfMonth, getWeekNumber, getStartDateOfMonth, DAY_DURATION } from '../util'; import { getFirstDayOfMonth, getDayCountOfMonth, getWeekNumber, getStartDateOfMonth, DAY_DURATION } from '../util';
import { hasClass } from 'wind-dom/src/class'; import { hasClass } from 'element-ui/src/utils/dom';
import Locale from 'element-ui/src/mixins/locale'; import Locale from 'element-ui/src/mixins/locale';
const clearHours = function(time) { const clearHours = function(time) {

View File

@ -49,7 +49,7 @@
<script type="text/babel"> <script type="text/babel">
import Locale from 'element-ui/src/mixins/locale'; import Locale from 'element-ui/src/mixins/locale';
import { hasClass } from 'wind-dom/src/class'; import { hasClass } from 'element-ui/src/utils/dom';
export default { export default {
props: { props: {

View File

@ -44,7 +44,7 @@
</template> </template>
<script type="text/babel"> <script type="text/babel">
import { hasClass } from 'wind-dom/src/class'; import { hasClass } from 'element-ui/src/utils/dom';
export default { export default {
props: { props: {

View File

@ -22,7 +22,7 @@
</template> </template>
<script> <script>
import Popup from 'vue-popup'; import Popup from 'element-ui/src/utils/popup';
export default { export default {
name: 'el-dialog', name: 'el-dialog',

View File

@ -13,6 +13,5 @@
"license": "MIT", "license": "MIT",
"repository": "https://github.com/ElemeFE/element/tree/master/packages/input-number", "repository": "https://github.com/ElemeFE/element/tree/master/packages/input-number",
"dependencies": { "dependencies": {
"wind-dom": "0.0.3"
} }
} }

View File

@ -46,7 +46,7 @@
</template> </template>
<script> <script>
import ElInput from 'element-ui/packages/input'; import ElInput from 'element-ui/packages/input';
import { once, on } from 'wind-dom/src/event'; import { once, on } from 'element-ui/src/utils/dom';
export default { export default {
name: 'ElInputNumber', name: 'ElInputNumber',

View File

@ -12,6 +12,5 @@
"author": "elemefe", "author": "elemefe",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"wind-dom": "0.0.3"
} }
} }

View File

@ -1,5 +1,5 @@
import Vue from 'vue'; import Vue from 'vue';
import { addClass, removeClass } from 'wind-dom/src/class'; import { addClass, removeClass } from 'element-ui/src/utils/dom';
let Mask = Vue.extend(require('./loading.vue')); let Mask = Vue.extend(require('./loading.vue'));
exports.install = Vue => { exports.install = Vue => {

View File

@ -12,6 +12,5 @@
"author": "elemefe", "author": "elemefe",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"wind-dom": "0.0.3"
} }
} }

View File

@ -12,6 +12,5 @@
"author": "elemefe", "author": "elemefe",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"wind-dom": "0.0.3"
} }
} }

View File

@ -24,11 +24,11 @@
</template> </template>
<script type="text/babel"> <script type="text/babel">
import Popup from 'vue-popup'; import Popup from 'element-ui/src/utils/popup';
import Locale from 'element-ui/src/mixins/locale'; import Locale from 'element-ui/src/mixins/locale';
import ElInput from 'element-ui/packages/input'; import ElInput from 'element-ui/packages/input';
import ElButton from 'element-ui/packages/button'; import ElButton from 'element-ui/packages/button';
import { addClass, removeClass } from 'wind-dom/src/class'; import { addClass, removeClass } from 'element-ui/src/utils/dom';
import { t } from 'element-ui/src/locale'; import { t } from 'element-ui/src/locale';
let typeMap = { let typeMap = {

View File

@ -1,5 +1,5 @@
import Vue from 'vue'; import Vue from 'vue';
import { PopupManager } from 'vue-popup'; import { PopupManager } from 'element-ui/src/utils/popup';
let MessageConstructor = Vue.extend(require('./main.vue')); let MessageConstructor = Vue.extend(require('./main.vue'));
let instance; let instance;

View File

@ -1,5 +1,5 @@
import Vue from 'vue'; import Vue from 'vue';
import { PopupManager } from 'vue-popup'; import { PopupManager } from 'element-ui/src/utils/popup';
let NotificationConstructor = Vue.extend(require('./main.vue')); let NotificationConstructor = Vue.extend(require('./main.vue'));
let instance; let instance;

View File

@ -12,6 +12,5 @@
"author": "elemefe", "author": "elemefe",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"wind-dom": "0.0.3"
} }
} }

View File

@ -17,7 +17,7 @@
<script> <script>
import Popper from 'element-ui/src/utils/vue-popper'; import Popper from 'element-ui/src/utils/vue-popper';
import { on, off } from 'wind-dom/src/event'; import { on, off } from 'element-ui/src/utils/dom';
export default { export default {
name: 'el-popover', name: 'el-popover',

View File

@ -12,6 +12,5 @@
"author": "elemefe", "author": "elemefe",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"wind-dom": "0.0.3"
} }
} }

View File

@ -24,7 +24,7 @@
</template> </template>
<script type="text/babel"> <script type="text/babel">
import { hasClass } from 'wind-dom/src/class'; import { hasClass } from 'element-ui/src/utils/dom';
export default { export default {
name: 'el-rate', name: 'el-rate',

View File

@ -12,7 +12,6 @@
"license": "MIT", "license": "MIT",
"repository": "https://github.com/ElemeFE/element/tree/master/packages/select", "repository": "https://github.com/ElemeFE/element/tree/master/packages/select",
"devDependencies": { "devDependencies": {
"throttle-debounce": "^1.0.1", "throttle-debounce": "^1.0.1"
"wind-dom": "0.0.3"
} }
} }

View File

@ -91,7 +91,7 @@
import ElTag from 'element-ui/packages/tag'; import ElTag from 'element-ui/packages/tag';
import debounce from 'throttle-debounce/debounce'; import debounce from 'throttle-debounce/debounce';
import Clickoutside from 'element-ui/src/utils/clickoutside'; import Clickoutside from 'element-ui/src/utils/clickoutside';
import { addClass, removeClass, hasClass } from 'wind-dom/src/class'; import { addClass, removeClass, hasClass } from 'element-ui/src/utils/dom';
import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event'; import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event';
import { t } from 'element-ui/src/locale'; import { t } from 'element-ui/src/locale';
const sizeMap = { const sizeMap = {

View File

@ -12,6 +12,5 @@
"author": "elemefe", "author": "elemefe",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"wind-dom": "0.0.3"
} }
} }

View File

@ -37,7 +37,7 @@
<script type="text/babel"> <script type="text/babel">
import ElInputNumber from 'element-ui/packages/input-number'; import ElInputNumber from 'element-ui/packages/input-number';
import ElTooltip from 'element-ui/packages/tooltip'; import ElTooltip from 'element-ui/packages/tooltip';
import { getStyle } from 'wind-dom/src/style'; import { getStyle } from 'element-ui/src/utils/dom';
export default { export default {
name: 'ElSlider', name: 'ElSlider',

View File

@ -1,4 +1,5 @@
import { getScrollBarWidth } from './util'; import { getScrollBarWidth } from './util';
import Vue from 'vue';
let GUTTER_WIDTH; let GUTTER_WIDTH;
@ -22,7 +23,7 @@ class TableLayout {
this.bodyHeight = null; // Table Height - Table Header Height this.bodyHeight = null; // Table Height - Table Header Height
this.fixedBodyHeight = null; // Table Height - Table Header Height - Scroll Bar Height this.fixedBodyHeight = null; // Table Height - Table Header Height - Scroll Bar Height
if (GUTTER_WIDTH === undefined) { if (GUTTER_WIDTH === undefined && !Vue.prototype.$isServer) {
GUTTER_WIDTH = getScrollBarWidth(); GUTTER_WIDTH = getScrollBarWidth();
} }
this.gutterWidth = GUTTER_WIDTH; this.gutterWidth = GUTTER_WIDTH;

View File

@ -31,7 +31,5 @@
"gulp-postcss": "^6.1.1", "gulp-postcss": "^6.1.1",
"postcss-salad": "^1.0.5" "postcss-salad": "^1.0.5"
}, },
"dependencies": { "dependencies": {}
"vue-popup": "^0.2.9"
}
} }

View File

@ -0,0 +1,33 @@
.v-modal-enter {
animation: v-modal-in .2s ease;
}
.v-modal-leave {
animation: v-modal-out .2s ease forwards;
}
@keyframes v-modal-in {
0% {
opacity: 0;
}
100% {
}
}
@keyframes v-modal-out {
0% {
}
100% {
opacity: 0;
}
}
.v-modal {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
opacity: 0.5;
background: #000;
}

View File

@ -1,6 +1,6 @@
@charset "UTF-8"; @charset "UTF-8";
@import "./common/var.css"; @import "./common/var.css";
@import "vue-popup/lib/popup.css"; @import "./common/popup.css";
@component-namespace el { @component-namespace el {

View File

@ -1,8 +1,8 @@
@charset "UTF-8"; @charset "UTF-8";
@import "./common/var.css"; @import "./common/var.css";
@import "./common/popup.css";
@import "./button.css"; @import "./button.css";
@import "./input.css"; @import "./input.css";
@import "vue-popup/lib/popup.css";
@component-namespace el { @component-namespace el {

View File

@ -1,5 +1,5 @@
import Vue from 'vue'; import Vue from 'vue';
import { on } from 'wind-dom/src/event'; import { on } from 'element-ui/src/utils/dom';
const nodeList = []; const nodeList = [];
const ctx = '@@clickoutsideContext'; const ctx = '@@clickoutsideContext';

178
src/utils/dom.js Normal file
View File

@ -0,0 +1,178 @@
/* istanbul ignore next */
import Vue from 'vue';
const isServer = Vue.prototype.$isServer;
const SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;
const MOZ_HACK_REGEXP = /^moz([A-Z])/;
const ieVersion = isServer ? 0 : Number(document.documentMode);
/* istanbul ignore next */
const trim = function(string) {
return (string || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, '');
};
/* istanbul ignore next */
const camelCase = function(name) {
return name.replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {
return offset ? letter.toUpperCase() : letter;
}).replace(MOZ_HACK_REGEXP, 'Moz$1');
};
/* istanbul ignore next */
export const on = (function() {
if (!isServer && document.addEventListener) {
return function(element, event, handler) {
if (element && event && handler) {
element.addEventListener(event, handler, false);
}
};
} else {
return function(element, event, handler) {
if (element && event && handler) {
element.attachEvent('on' + event, handler);
}
};
}
})();
/* istanbul ignore next */
export const off = (function() {
if (!isServer && document.removeEventListener) {
return function(element, event, handler) {
if (element && event) {
element.removeEventListener(event, handler, false);
}
};
} else {
return function(element, event, handler) {
if (element && event) {
element.detachEvent('on' + event, handler);
}
};
}
})();
/* istanbul ignore next */
export const once = function(el, event, fn) {
var listener = function() {
if (fn) {
fn.apply(this, arguments);
}
off(el, event, listener);
};
on(el, event, listener);
};
/* istanbul ignore next */
export function hasClass(el, cls) {
if (!el || !cls) return false;
if (cls.indexOf(' ') !== -1) throw new Error('className should not contain space.');
if (el.classList) {
return el.classList.contains(cls);
} else {
return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1;
}
};
/* istanbul ignore next */
export function addClass(el, cls) {
if (!el) return;
var curClass = el.className;
var classes = (cls || '').split(' ');
for (var i = 0, j = classes.length; i < j; i++) {
var clsName = classes[i];
if (!clsName) continue;
if (el.classList) {
el.classList.add(clsName);
} else {
if (!hasClass(el, clsName)) {
curClass += ' ' + clsName;
}
}
}
if (!el.classList) {
el.className = curClass;
}
};
/* istanbul ignore next */
export function removeClass(el, cls) {
if (!el || !cls) return;
var classes = cls.split(' ');
var curClass = ' ' + el.className + ' ';
for (var i = 0, j = classes.length; i < j; i++) {
var clsName = classes[i];
if (!clsName) continue;
if (el.classList) {
el.classList.remove(clsName);
} else {
if (hasClass(el, clsName)) {
curClass = curClass.replace(' ' + clsName + ' ', ' ');
}
}
}
if (!el.classList) {
el.className = trim(curClass);
}
};
/* istanbul ignore next */
export const getStyle = ieVersion < 9 ? function(element, styleName) {
if (isServer) return;
if (!element || !styleName) return null;
styleName = camelCase(styleName);
if (styleName === 'float') {
styleName = 'styleFloat';
}
try {
switch (styleName) {
case 'opacity':
try {
return element.filters.item('alpha').opacity / 100;
} catch (e) {
return 1.0;
}
default:
return (element.style[styleName] || element.currentStyle ? element.currentStyle[styleName] : null);
}
} catch (e) {
return element.style[styleName];
}
} : function(element, styleName) {
if (isServer) return;
if (!element || !styleName) return null;
styleName = camelCase(styleName);
if (styleName === 'float') {
styleName = 'cssFloat';
}
try {
var computed = document.defaultView.getComputedStyle(element, '');
return element.style[styleName] || computed ? computed[styleName] : null;
} catch (e) {
return element.style[styleName];
}
};
/* istanbul ignore next */
export function setStyle(element, styleName, value) {
if (!element || !styleName) return;
if (typeof styleName === 'object') {
for (var prop in styleName) {
if (styleName.hasOwnProperty(prop)) {
setStyle(element, prop, styleName[prop]);
}
}
} else {
styleName = camelCase(styleName);
if (styleName === 'opacity' && ieVersion < 9) {
element.style.filter = isNaN(value) ? '' : 'alpha(opacity=' + value * 100 + ')';
} else {
element.style[styleName] = value;
}
}
};

297
src/utils/popup/index.js Normal file
View File

@ -0,0 +1,297 @@
import Vue from 'vue';
import merge from 'element-ui/src/utils/merge';
import PopupManager from 'element-ui/src/utils/popup/popup-manager';
let idSeed = 1;
const transitions = [];
const hookTransition = (transition) => {
if (transitions.indexOf(transition) !== -1) return;
const getVueInstance = (element) => {
let instance = element.__vue__;
if (!instance) {
const textNode = element.previousSibling;
if (textNode.__vue__) {
instance = textNode.__vue__;
}
}
return instance;
};
Vue.transition(transition, {
afterEnter(el) {
const instance = getVueInstance(el);
if (instance) {
instance.doAfterOpen && instance.doAfterOpen();
}
},
afterLeave(el) {
const instance = getVueInstance(el);
if (instance) {
instance.doAfterClose && instance.doAfterClose();
}
}
});
};
let scrollBarWidth;
const getScrollBarWidth = () => {
if (Vue.prototype.$isServer) return;
if (scrollBarWidth !== undefined) return scrollBarWidth;
const outer = document.createElement('div');
outer.style.visibility = 'hidden';
outer.style.width = '100px';
outer.style.position = 'absolute';
outer.style.top = '-9999px';
document.body.appendChild(outer);
const widthNoScroll = outer.offsetWidth;
outer.style.overflow = 'scroll';
const inner = document.createElement('div');
inner.style.width = '100%';
outer.appendChild(inner);
const widthWithScroll = inner.offsetWidth;
outer.parentNode.removeChild(outer);
return widthNoScroll - widthWithScroll;
};
const getDOM = function(dom) {
if (dom.nodeType === 3) {
dom = dom.nextElementSibling || dom.nextSibling;
getDOM(dom);
}
return dom;
};
export default {
props: {
value: {
type: Boolean,
default: false
},
transition: {
type: String,
default: ''
},
openDelay: {},
closeDelay: {},
zIndex: {},
modal: {
type: Boolean,
default: false
},
modalFade: {
type: Boolean,
default: true
},
modalClass: {
},
lockScroll: {
type: Boolean,
default: true
},
closeOnPressEscape: {
type: Boolean,
default: false
},
closeOnClickModal: {
type: Boolean,
default: false
}
},
created() {
if (this.transition) {
hookTransition(this.transition);
}
},
beforeMount() {
this._popupId = 'popup-' + idSeed++;
PopupManager.register(this._popupId, this);
},
beforeDestroy() {
PopupManager.deregister(this._popupId);
PopupManager.closeModal(this._popupId);
if (this.modal && this.bodyOverflow !== null && this.bodyOverflow !== 'hidden') {
document.body.style.overflow = this.bodyOverflow;
document.body.style.paddingRight = this.bodyPaddingRight;
}
this.bodyOverflow = null;
this.bodyPaddingRight = null;
},
data() {
return {
opened: false,
bodyOverflow: null,
bodyPaddingRight: null,
rendered: false
};
},
watch: {
value(val) {
if (val) {
if (this._opening) return;
if (!this.rendered) {
this.rendered = true;
Vue.nextTick(() => {
this.open();
});
} else {
this.open();
}
} else {
this.close();
}
}
},
methods: {
open(options) {
if (!this.rendered) {
this.rendered = true;
this.$emit('input', true);
}
const props = merge({}, this, options);
if (this._closeTimer) {
clearTimeout(this._closeTimer);
this._closeTimer = null;
}
clearTimeout(this._openTimer);
const openDelay = Number(props.openDelay);
if (openDelay > 0) {
this._openTimer = setTimeout(() => {
this._openTimer = null;
this.doOpen(props);
}, openDelay);
} else {
this.doOpen(props);
}
},
doOpen(props) {
if (this.$isServer) return;
if (this.willOpen && !this.willOpen()) return;
if (this.opened) return;
this._opening = true;
// 使用 vue-popup 的组件,如果需要和父组件通信显示的状态,应该使用 value它是一个 prop
// 这样在父组件中用 v-model 即可;否则可以使用 visible它是一个 data
this.visible = true;
this.$emit('input', true);
const dom = getDOM(this.$el);
const modal = props.modal;
const zIndex = props.zIndex;
if (zIndex) {
PopupManager.zIndex = zIndex;
}
if (modal) {
if (this._closing) {
PopupManager.closeModal(this._popupId);
this._closing = false;
}
PopupManager.openModal(this._popupId, PopupManager.nextZIndex(), dom, props.modalClass, props.modalFade);
if (props.lockScroll) {
if (!this.bodyOverflow) {
this.bodyPaddingRight = document.body.style.paddingRight;
this.bodyOverflow = document.body.style.overflow;
}
scrollBarWidth = getScrollBarWidth();
let bodyHasOverflow = document.documentElement.clientHeight < document.body.scrollHeight;
if (scrollBarWidth > 0 && bodyHasOverflow) {
document.body.style.paddingRight = scrollBarWidth + 'px';
}
document.body.style.overflow = 'hidden';
}
}
if (getComputedStyle(dom).position === 'static') {
dom.style.position = 'absolute';
}
dom.style.zIndex = PopupManager.nextZIndex();
this.opened = true;
this.onOpen && this.onOpen();
if (!this.transition) {
this.doAfterOpen();
}
},
doAfterOpen() {
this._opening = false;
},
close() {
if (this.willClose && !this.willClose()) return;
if (this._openTimer !== null) {
clearTimeout(this._openTimer);
this._openTimer = null;
}
clearTimeout(this._closeTimer);
const closeDelay = Number(this.closeDelay);
if (closeDelay > 0) {
this._closeTimer = setTimeout(() => {
this._closeTimer = null;
this.doClose();
}, closeDelay);
} else {
this.doClose();
}
},
doClose() {
this.visible = false;
this.$emit('input', false);
this._closing = true;
this.onClose && this.onClose();
if (this.lockScroll) {
setTimeout(() => {
if (this.modal && this.bodyOverflow !== 'hidden') {
document.body.style.overflow = this.bodyOverflow;
document.body.style.paddingRight = this.bodyPaddingRight;
}
this.bodyOverflow = null;
this.bodyPaddingRight = null;
}, 200);
}
this.opened = false;
if (!this.transition) {
this.doAfterClose();
}
},
doAfterClose() {
PopupManager.closeModal(this._popupId);
this._closing = false;
}
}
};
export { PopupManager };

View File

@ -0,0 +1,165 @@
import Vue from 'vue';
import { addClass, removeClass } from 'element-ui/src/utils/dom';
let hasModal = false;
const getModal = function() {
if (Vue.prototype.$isServer) return;
let modalDom = PopupManager.modalDom;
if (modalDom) {
hasModal = true;
} else {
hasModal = false;
modalDom = document.createElement('div');
PopupManager.modalDom = modalDom;
modalDom.addEventListener('touchmove', function(event) {
event.preventDefault();
event.stopPropagation();
});
modalDom.addEventListener('click', function() {
PopupManager.doOnModalClick && PopupManager.doOnModalClick();
});
}
return modalDom;
};
const instances = {};
const PopupManager = {
zIndex: 2000,
modalFade: true,
getInstance: function(id) {
return instances[id];
},
register: function(id, instance) {
if (id && instance) {
instances[id] = instance;
}
},
deregister: function(id) {
if (id) {
instances[id] = null;
delete instances[id];
}
},
nextZIndex: function() {
return PopupManager.zIndex++;
},
modalStack: [],
doOnModalClick: function() {
const topItem = PopupManager.modalStack[PopupManager.modalStack.length - 1];
if (!topItem) return;
const instance = PopupManager.getInstance(topItem.id);
if (instance && instance.closeOnClickModal) {
instance.close();
}
},
openModal: function(id, zIndex, dom, modalClass, modalFade) {
if (Vue.prototype.$isServer) return;
if (!id || zIndex === undefined) return;
this.modalFade = modalFade;
const modalStack = this.modalStack;
for (let i = 0, j = modalStack.length; i < j; i++) {
const item = modalStack[i];
if (item.id === id) {
return;
}
}
const modalDom = getModal();
addClass(modalDom, 'v-modal');
if (this.modalFade && !hasModal) {
addClass(modalDom, 'v-modal-enter');
}
if (modalClass) {
let classArr = modalClass.trim().split(/\s+/);
classArr.forEach(item => addClass(modalDom, item));
}
setTimeout(() => {
removeClass(modalDom, 'v-modal-enter');
}, 200);
if (dom && dom.parentNode && dom.parentNode.nodeType !== 11) {
dom.parentNode.appendChild(modalDom);
} else {
document.body.appendChild(modalDom);
}
if (zIndex) {
modalDom.style.zIndex = zIndex;
}
modalDom.style.display = '';
this.modalStack.push({ id: id, zIndex: zIndex, modalClass: modalClass });
},
closeModal: function(id) {
const modalStack = this.modalStack;
const modalDom = getModal();
if (modalStack.length > 0) {
const topItem = modalStack[modalStack.length - 1];
if (topItem.id === id) {
if (topItem.modalClass) {
let classArr = topItem.modalClass.trim().split(/\s+/);
classArr.forEach(item => removeClass(modalDom, item));
}
modalStack.pop();
if (modalStack.length > 0) {
modalDom.style.zIndex = modalStack[modalStack.length - 1].zIndex;
}
} else {
for (let i = modalStack.length - 1; i >= 0; i--) {
if (modalStack[i].id === id) {
modalStack.splice(i, 1);
break;
}
}
}
}
if (modalStack.length === 0) {
if (this.modalFade) {
addClass(modalDom, 'v-modal-leave');
}
setTimeout(() => {
if (modalStack.length === 0) {
if (modalDom.parentNode) modalDom.parentNode.removeChild(modalDom);
modalDom.style.display = 'none';
PopupManager.modalDom = undefined;
}
removeClass(modalDom, 'v-modal-leave');
}, 200);
}
}
};
!Vue.prototype.$isServer && window.addEventListener('keydown', function(event) {
if (event.keyCode === 27) { // ESC
if (PopupManager.modalStack.length > 0) {
const topItem = PopupManager.modalStack[PopupManager.modalStack.length - 1];
if (!topItem) return;
const instance = PopupManager.getInstance(topItem.id);
if (instance.closeOnPressEscape) {
instance.close();
}
}
}
});
export default PopupManager;

View File

@ -166,4 +166,4 @@ export const removeResizeListener = function(element, fn) {
element.__resizeTrigger__ = !element.removeChild(element.__resizeTrigger__); element.__resizeTrigger__ = !element.removeChild(element.__resizeTrigger__);
} }
} }
}; };

View File

@ -1,6 +1,7 @@
import PopperJS from './popper'; import Vue from 'vue';
import { PopupManager } from 'vue-popup'; import { PopupManager } from 'element-ui/src/utils/popup';
const PopperJS = Vue.prototype.$isServer ? function() {} : require('./popper');
const stop = e => e.stopPropagation(); const stop = e => e.stopPropagation();
/** /**

View File

@ -1,4 +1,4 @@
import VuePopup from 'vue-popup'; import VuePopup from 'element-ui/src/utils/popup';
import { createTest, destroyVM } from '../util'; import { createTest, destroyVM } from '../util';
const Popup = Object.assign({}, VuePopup, { const Popup = Object.assign({}, VuePopup, {

View File

@ -6863,12 +6863,6 @@ vue-markdown-loader@^0.5.1:
markdown-it "^6.0.5" markdown-it "^6.0.5"
rimraf "^2.5.2" rimraf "^2.5.2"
vue-popup@^0.2.14:
version "0.2.14"
resolved "https://registry.yarnpkg.com/vue-popup/-/vue-popup-0.2.14.tgz#aa3d461c6f2ab01ef4546665d730395ec6028302"
dependencies:
wind-dom "0.0.3"
vue-router@^2.0.0: vue-router@^2.0.0:
version "2.1.1" version "2.1.1"
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-2.1.1.tgz#10c31bbdcb6da92bd3e0223fa12345e73018625a" resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-2.1.1.tgz#10c31bbdcb6da92bd3e0223fa12345e73018625a"
@ -7020,10 +7014,6 @@ wide-align@^1.1.0:
dependencies: dependencies:
string-width "^1.0.1" string-width "^1.0.1"
wind-dom@0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/wind-dom/-/wind-dom-0.0.3.tgz#3456e3d959dbebdcbf76ca68c6a4e8142f26360f"
window-size@^0.2.0: window-size@^0.2.0:
version "0.2.0" version "0.2.0"
resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075"