| 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, _ => { | 
|         if (!el.instance.hiding) return; | 
|         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' && el.originalPosition !== 'sticky') { | 
|         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; | 
|     } else if (el.domVisible && el.instance.hiding === true) { | 
|       el.instance.visible = true; | 
|       el.instance.hiding = false; | 
|     } | 
|   }; | 
|   | 
|   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; |