mirror of https://github.com/ElemeFE/element
130 lines
4.4 KiB
JavaScript
130 lines
4.4 KiB
JavaScript
import Vue from 'vue';
|
|
import Loading from './loading.vue';
|
|
import { addClass, removeClass, getStyle } from 'element-ui/src/utils/dom';
|
|
import { PopupManager } from 'element-ui/src/utils/popup';
|
|
import afterLeave from 'element-ui/src/utils/after-leave';
|
|
const Mask = Vue.extend(Loading);
|
|
|
|
const loadingDirective = {};
|
|
loadingDirective.install = Vue => {
|
|
if (Vue.prototype.$isServer) return;
|
|
const toggleLoading = (el, binding) => {
|
|
if (binding.value) {
|
|
Vue.nextTick(() => {
|
|
if (binding.modifiers.fullscreen) {
|
|
el.originalPosition = getStyle(document.body, 'position');
|
|
el.originalOverflow = getStyle(document.body, 'overflow');
|
|
el.maskStyle.zIndex = PopupManager.nextZIndex();
|
|
|
|
addClass(el.mask, 'is-fullscreen');
|
|
insertDom(document.body, el, binding);
|
|
} else {
|
|
removeClass(el.mask, 'is-fullscreen');
|
|
|
|
if (binding.modifiers.body) {
|
|
el.originalPosition = getStyle(document.body, 'position');
|
|
|
|
['top', 'left'].forEach(property => {
|
|
const scroll = property === 'top' ? 'scrollTop' : 'scrollLeft';
|
|
el.maskStyle[property] = el.getBoundingClientRect()[property] +
|
|
document.body[scroll] +
|
|
document.documentElement[scroll] -
|
|
parseInt(getStyle(document.body, `margin-${ property }`), 10) +
|
|
'px';
|
|
});
|
|
['height', 'width'].forEach(property => {
|
|
el.maskStyle[property] = el.getBoundingClientRect()[property] + 'px';
|
|
});
|
|
|
|
insertDom(document.body, el, binding);
|
|
} else {
|
|
el.originalPosition = getStyle(el, 'position');
|
|
insertDom(el, el, binding);
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
afterLeave(el.instance, _ => {
|
|
el.domVisible = false;
|
|
const target = binding.modifiers.fullscreen || binding.modifiers.body
|
|
? document.body
|
|
: el;
|
|
removeClass(target, 'el-loading-parent--relative');
|
|
removeClass(target, 'el-loading-parent--hidden');
|
|
el.instance.hiding = false;
|
|
}, 300, true);
|
|
el.instance.visible = false;
|
|
el.instance.hiding = true;
|
|
}
|
|
};
|
|
const insertDom = (parent, el, binding) => {
|
|
if (!el.domVisible && getStyle(el, 'display') !== 'none' && getStyle(el, 'visibility') !== 'hidden') {
|
|
Object.keys(el.maskStyle).forEach(property => {
|
|
el.mask.style[property] = el.maskStyle[property];
|
|
});
|
|
|
|
if (el.originalPosition !== 'absolute' && el.originalPosition !== 'fixed') {
|
|
addClass(parent, 'el-loading-parent--relative');
|
|
}
|
|
if (binding.modifiers.fullscreen && binding.modifiers.lock) {
|
|
addClass(parent, 'el-loading-parent--hidden');
|
|
}
|
|
el.domVisible = true;
|
|
|
|
parent.appendChild(el.mask);
|
|
Vue.nextTick(() => {
|
|
if (el.instance.hiding) {
|
|
el.instance.$emit('after-leave');
|
|
} else {
|
|
el.instance.visible = true;
|
|
}
|
|
});
|
|
el.domInserted = true;
|
|
}
|
|
};
|
|
|
|
Vue.directive('loading', {
|
|
bind: function(el, binding, vnode) {
|
|
const textExr = el.getAttribute('element-loading-text');
|
|
const spinnerExr = el.getAttribute('element-loading-spinner');
|
|
const backgroundExr = el.getAttribute('element-loading-background');
|
|
const customClassExr = el.getAttribute('element-loading-custom-class');
|
|
const vm = vnode.context;
|
|
const mask = new Mask({
|
|
el: document.createElement('div'),
|
|
data: {
|
|
text: vm && vm[textExr] || textExr,
|
|
spinner: vm && vm[spinnerExr] || spinnerExr,
|
|
background: vm && vm[backgroundExr] || backgroundExr,
|
|
customClass: vm && vm[customClassExr] || customClassExr,
|
|
fullscreen: !!binding.modifiers.fullscreen
|
|
}
|
|
});
|
|
el.instance = mask;
|
|
el.mask = mask.$el;
|
|
el.maskStyle = {};
|
|
|
|
binding.value && toggleLoading(el, binding);
|
|
},
|
|
|
|
update: function(el, binding) {
|
|
el.instance.setText(el.getAttribute('element-loading-text'));
|
|
if (binding.oldValue !== binding.value) {
|
|
toggleLoading(el, binding);
|
|
}
|
|
},
|
|
|
|
unbind: function(el, binding) {
|
|
if (el.domInserted) {
|
|
el.mask &&
|
|
el.mask.parentNode &&
|
|
el.mask.parentNode.removeChild(el.mask);
|
|
toggleLoading(el, { value: false, modifiers: binding.modifiers });
|
|
}
|
|
el.instance && el.instance.$destroy();
|
|
}
|
|
});
|
|
};
|
|
|
|
export default loadingDirective;
|