1 | import Vue from 'vue';
|
2 | import loadingVue from './loading.vue';
|
3 | import { addClass, removeClass, getStyle } from 'element-ui/src/utils/dom';
|
4 | import { PopupManager } from 'element-ui/src/utils/popup';
|
5 | import afterLeave from 'element-ui/src/utils/after-leave';
|
6 | import merge from 'element-ui/src/utils/merge';
|
7 |
|
8 | const LoadingConstructor = Vue.extend(loadingVue);
|
9 |
|
10 | const defaults = {
|
11 | text: null,
|
12 | fullscreen: true,
|
13 | body: false,
|
14 | lock: false,
|
15 | customClass: ''
|
16 | };
|
17 |
|
18 | let fullscreenLoading;
|
19 |
|
20 | LoadingConstructor.prototype.originalPosition = '';
|
21 | LoadingConstructor.prototype.originalOverflow = '';
|
22 |
|
23 | LoadingConstructor.prototype.close = function() {
|
24 | if (this.fullscreen) {
|
25 | fullscreenLoading = undefined;
|
26 | }
|
27 | afterLeave(this, _ => {
|
28 | const target = this.fullscreen || this.body
|
29 | ? document.body
|
30 | : this.target;
|
31 | removeClass(target, 'el-loading-parent--relative');
|
32 | removeClass(target, 'el-loading-parent--hidden');
|
33 | if (this.$el && this.$el.parentNode) {
|
34 | this.$el.parentNode.removeChild(this.$el);
|
35 | }
|
36 | this.$destroy();
|
37 | }, 300);
|
38 | this.visible = false;
|
39 | };
|
40 |
|
41 | const addStyle = (options, parent, instance) => {
|
42 | let maskStyle = {};
|
43 | if (options.fullscreen) {
|
44 | instance.originalPosition = getStyle(document.body, 'position');
|
45 | instance.originalOverflow = getStyle(document.body, 'overflow');
|
46 | maskStyle.zIndex = PopupManager.nextZIndex();
|
47 | } else if (options.body) {
|
48 | instance.originalPosition = getStyle(document.body, 'position');
|
49 | ['top', 'left'].forEach(property => {
|
50 | let scroll = property === 'top' ? 'scrollTop' : 'scrollLeft';
|
51 | maskStyle[property] = options.target.getBoundingClientRect()[property] +
|
52 | document.body[scroll] +
|
53 | document.documentElement[scroll] +
|
54 | 'px';
|
55 | });
|
56 | ['height', 'width'].forEach(property => {
|
57 | maskStyle[property] = options.target.getBoundingClientRect()[property] + 'px';
|
58 | });
|
59 | } else {
|
60 | instance.originalPosition = getStyle(parent, 'position');
|
61 | }
|
62 | Object.keys(maskStyle).forEach(property => {
|
63 | instance.$el.style[property] = maskStyle[property];
|
64 | });
|
65 | };
|
66 |
|
67 | const Loading = (options = {}) => {
|
68 | if (Vue.prototype.$isServer) return;
|
69 | options = merge({}, defaults, options);
|
70 | if (typeof options.target === 'string') {
|
71 | options.target = document.querySelector(options.target);
|
72 | }
|
73 | options.target = options.target || document.body;
|
74 | if (options.target !== document.body) {
|
75 | options.fullscreen = false;
|
76 | } else {
|
77 | options.body = true;
|
78 | }
|
79 | if (options.fullscreen && fullscreenLoading) {
|
80 | return fullscreenLoading;
|
81 | }
|
82 |
|
83 | let parent = options.body ? document.body : options.target;
|
84 | let instance = new LoadingConstructor({
|
85 | el: document.createElement('div'),
|
86 | data: options
|
87 | });
|
88 |
|
89 | addStyle(options, parent, instance);
|
90 | if (instance.originalPosition !== 'absolute' && instance.originalPosition !== 'fixed') {
|
91 | addClass(parent, 'el-loading-parent--relative');
|
92 | }
|
93 | if (options.fullscreen && options.lock) {
|
94 | addClass(parent, 'el-loading-parent--hidden');
|
95 | }
|
96 | parent.appendChild(instance.$el);
|
97 | Vue.nextTick(() => {
|
98 | instance.visible = true;
|
99 | });
|
100 | if (options.fullscreen) {
|
101 | fullscreenLoading = instance;
|
102 | }
|
103 | return instance;
|
104 | };
|
105 |
|
106 | export default Loading;
|