UNPKG

4.49 kBJavaScriptView Raw
1import Vue from 'vue';
2import Loading from './loading.vue';
3import { addClass, removeClass, getStyle } from 'element-ui/src/utils/dom';
4import { PopupManager } from 'element-ui/src/utils/popup';
5import afterLeave from 'element-ui/src/utils/after-leave';
6const Mask = Vue.extend(Loading);
7
8const loadingDirective = {};
9loadingDirective.install = Vue => {
10 if (Vue.prototype.$isServer) return;
11 const toggleLoading = (el, binding) => {
12 if (binding.value) {
13 Vue.nextTick(() => {
14 if (binding.modifiers.fullscreen) {
15 el.originalPosition = getStyle(document.body, 'position');
16 el.originalOverflow = getStyle(document.body, 'overflow');
17 el.maskStyle.zIndex = PopupManager.nextZIndex();
18
19 addClass(el.mask, 'is-fullscreen');
20 insertDom(document.body, el, binding);
21 } else {
22 removeClass(el.mask, 'is-fullscreen');
23
24 if (binding.modifiers.body) {
25 el.originalPosition = getStyle(document.body, 'position');
26
27 ['top', 'left'].forEach(property => {
28 const scroll = property === 'top' ? 'scrollTop' : 'scrollLeft';
29 el.maskStyle[property] = el.getBoundingClientRect()[property] +
30 document.body[scroll] +
31 document.documentElement[scroll] -
32 parseInt(getStyle(document.body, `margin-${ property }`), 10) +
33 'px';
34 });
35 ['height', 'width'].forEach(property => {
36 el.maskStyle[property] = el.getBoundingClientRect()[property] + 'px';
37 });
38
39 insertDom(document.body, el, binding);
40 } else {
41 el.originalPosition = getStyle(el, 'position');
42 insertDom(el, el, binding);
43 }
44 }
45 });
46 } else {
47 afterLeave(el.instance, _ => {
48 el.domVisible = false;
49 const target = binding.modifiers.fullscreen || binding.modifiers.body
50 ? document.body
51 : el;
52 removeClass(target, 'el-loading-parent--relative');
53 removeClass(target, 'el-loading-parent--hidden');
54 el.instance.hiding = false;
55 }, 300, true);
56 el.instance.visible = false;
57 el.instance.hiding = true;
58 }
59 };
60 const insertDom = (parent, el, binding) => {
61 if (!el.domVisible && getStyle(el, 'display') !== 'none' && getStyle(el, 'visibility') !== 'hidden') {
62 Object.keys(el.maskStyle).forEach(property => {
63 el.mask.style[property] = el.maskStyle[property];
64 });
65
66 if (el.originalPosition !== 'absolute' && el.originalPosition !== 'fixed') {
67 addClass(parent, 'el-loading-parent--relative');
68 }
69 if (binding.modifiers.fullscreen && binding.modifiers.lock) {
70 addClass(parent, 'el-loading-parent--hidden');
71 }
72 el.domVisible = true;
73
74 parent.appendChild(el.mask);
75 Vue.nextTick(() => {
76 if (el.instance.hiding) {
77 el.instance.$emit('after-leave');
78 } else {
79 el.instance.visible = true;
80 }
81 });
82 el.domInserted = true;
83 }
84 };
85
86 Vue.directive('loading', {
87 bind: function(el, binding, vnode) {
88 const textExr = el.getAttribute('element-loading-text');
89 const spinnerExr = el.getAttribute('element-loading-spinner');
90 const backgroundExr = el.getAttribute('element-loading-background');
91 const customClassExr = el.getAttribute('element-loading-custom-class');
92 const vm = vnode.context;
93 const mask = new Mask({
94 el: document.createElement('div'),
95 data: {
96 text: vm && vm[textExr] || textExr,
97 spinner: vm && vm[spinnerExr] || spinnerExr,
98 background: vm && vm[backgroundExr] || backgroundExr,
99 customClass: vm && vm[customClassExr] || customClassExr,
100 fullscreen: !!binding.modifiers.fullscreen
101 }
102 });
103 el.instance = mask;
104 el.mask = mask.$el;
105 el.maskStyle = {};
106
107 binding.value && toggleLoading(el, binding);
108 },
109
110 update: function(el, binding) {
111 el.instance.setText(el.getAttribute('element-loading-text'));
112 if (binding.oldValue !== binding.value) {
113 toggleLoading(el, binding);
114 }
115 },
116
117 unbind: function(el, binding) {
118 if (el.domInserted) {
119 el.mask &&
120 el.mask.parentNode &&
121 el.mask.parentNode.removeChild(el.mask);
122 toggleLoading(el, { value: false, modifiers: binding.modifiers });
123 }
124 }
125 });
126};
127
128export default loadingDirective;