| import Popper from 'element-ui/src/utils/vue-popper'; | 
| import debounce from 'throttle-debounce/debounce'; | 
| import { addClass, removeClass, on, off } from 'element-ui/src/utils/dom'; | 
| import { generateId } from 'element-ui/src/utils/util'; | 
| import Vue from 'vue'; | 
|   | 
| export default { | 
|   name: 'ElTooltip', | 
|   | 
|   mixins: [Popper], | 
|   | 
|   props: { | 
|     openDelay: { | 
|       type: Number, | 
|       default: 0 | 
|     }, | 
|     disabled: Boolean, | 
|     manual: Boolean, | 
|     effect: { | 
|       type: String, | 
|       default: 'dark' | 
|     }, | 
|     arrowOffset: { | 
|       type: Number, | 
|       default: 0 | 
|     }, | 
|     popperClass: String, | 
|     content: String, | 
|     visibleArrow: { | 
|       default: true | 
|     }, | 
|     transition: { | 
|       type: String, | 
|       default: 'el-fade-in-linear' | 
|     }, | 
|     popperOptions: { | 
|       default() { | 
|         return { | 
|           boundariesPadding: 10, | 
|           gpuAcceleration: false | 
|         }; | 
|       } | 
|     }, | 
|     enterable: { | 
|       type: Boolean, | 
|       default: true | 
|     }, | 
|     hideAfter: { | 
|       type: Number, | 
|       default: 0 | 
|     }, | 
|     tabindex: { | 
|       type: Number, | 
|       default: 0 | 
|     } | 
|   }, | 
|   | 
|   data() { | 
|     return { | 
|       tooltipId: `el-tooltip-${generateId()}`, | 
|       timeoutPending: null, | 
|       focusing: false | 
|     }; | 
|   }, | 
|   beforeCreate() { | 
|     if (this.$isServer) return; | 
|   | 
|     this.popperVM = new Vue({ | 
|       data: { node: '' }, | 
|       render(h) { | 
|         return this.node; | 
|       } | 
|     }).$mount(); | 
|   | 
|     this.debounceClose = debounce(200, () => this.handleClosePopper()); | 
|   }, | 
|   | 
|   render(h) { | 
|     if (this.popperVM) { | 
|       this.popperVM.node = ( | 
|         <transition | 
|           name={ this.transition } | 
|           onAfterLeave={ this.doDestroy }> | 
|           <div | 
|             onMouseleave={ () => { this.setExpectedState(false); this.debounceClose(); } } | 
|             onMouseenter= { () => { this.setExpectedState(true); } } | 
|             ref="popper" | 
|             role="tooltip" | 
|             id={this.tooltipId} | 
|             aria-hidden={ (this.disabled || !this.showPopper) ? 'true' : 'false' } | 
|             v-show={!this.disabled && this.showPopper} | 
|             class={ | 
|               ['el-tooltip__popper', 'is-' + this.effect, this.popperClass] | 
|             }> | 
|             { this.$slots.content || this.content } | 
|           </div> | 
|         </transition>); | 
|     } | 
|   | 
|     const firstElement = this.getFirstElement(); | 
|     if (!firstElement) return null; | 
|   | 
|     const data = firstElement.data = firstElement.data || {}; | 
|     data.staticClass = this.addTooltipClass(data.staticClass); | 
|   | 
|     return firstElement; | 
|   }, | 
|   | 
|   mounted() { | 
|     this.referenceElm = this.$el; | 
|     if (this.$el.nodeType === 1) { | 
|       this.$el.setAttribute('aria-describedby', this.tooltipId); | 
|       this.$el.setAttribute('tabindex', this.tabindex); | 
|       on(this.referenceElm, 'mouseenter', this.show); | 
|       on(this.referenceElm, 'mouseleave', this.hide); | 
|       on(this.referenceElm, 'focus', () => { | 
|         if (!this.$slots.default || !this.$slots.default.length) { | 
|           this.handleFocus(); | 
|           return; | 
|         } | 
|         const instance = this.$slots.default[0].componentInstance; | 
|         if (instance && instance.focus) { | 
|           instance.focus(); | 
|         } else { | 
|           this.handleFocus(); | 
|         } | 
|       }); | 
|       on(this.referenceElm, 'blur', this.handleBlur); | 
|       on(this.referenceElm, 'click', this.removeFocusing); | 
|     } | 
|     // fix issue https://github.com/ElemeFE/element/issues/14424 | 
|     if (this.value && this.popperVM) { | 
|       this.popperVM.$nextTick(() => { | 
|         if (this.value) { | 
|           this.updatePopper(); | 
|         } | 
|       }); | 
|     } | 
|   }, | 
|   watch: { | 
|     focusing(val) { | 
|       if (val) { | 
|         addClass(this.referenceElm, 'focusing'); | 
|       } else { | 
|         removeClass(this.referenceElm, 'focusing'); | 
|       } | 
|     } | 
|   }, | 
|   methods: { | 
|     show() { | 
|       this.setExpectedState(true); | 
|       this.handleShowPopper(); | 
|     }, | 
|   | 
|     hide() { | 
|       this.setExpectedState(false); | 
|       this.debounceClose(); | 
|     }, | 
|     handleFocus() { | 
|       this.focusing = true; | 
|       this.show(); | 
|     }, | 
|     handleBlur() { | 
|       this.focusing = false; | 
|       this.hide(); | 
|     }, | 
|     removeFocusing() { | 
|       this.focusing = false; | 
|     }, | 
|   | 
|     addTooltipClass(prev) { | 
|       if (!prev) { | 
|         return 'el-tooltip'; | 
|       } else { | 
|         return 'el-tooltip ' + prev.replace('el-tooltip', ''); | 
|       } | 
|     }, | 
|   | 
|     handleShowPopper() { | 
|       if (!this.expectedState || this.manual) return; | 
|       clearTimeout(this.timeout); | 
|       this.timeout = setTimeout(() => { | 
|         this.showPopper = true; | 
|       }, this.openDelay); | 
|   | 
|       if (this.hideAfter > 0) { | 
|         this.timeoutPending = setTimeout(() => { | 
|           this.showPopper = false; | 
|         }, this.hideAfter); | 
|       } | 
|     }, | 
|   | 
|     handleClosePopper() { | 
|       if (this.enterable && this.expectedState || this.manual) return; | 
|       clearTimeout(this.timeout); | 
|   | 
|       if (this.timeoutPending) { | 
|         clearTimeout(this.timeoutPending); | 
|       } | 
|       this.showPopper = false; | 
|   | 
|       if (this.disabled) { | 
|         this.doDestroy(); | 
|       } | 
|     }, | 
|   | 
|     setExpectedState(expectedState) { | 
|       if (expectedState === false) { | 
|         clearTimeout(this.timeoutPending); | 
|       } | 
|       this.expectedState = expectedState; | 
|     }, | 
|   | 
|     getFirstElement() { | 
|       const slots = this.$slots.default; | 
|       if (!Array.isArray(slots)) return null; | 
|       let element = null; | 
|       for (let index = 0; index < slots.length; index++) { | 
|         if (slots[index] && slots[index].tag) { | 
|           element = slots[index]; | 
|           break; | 
|         }; | 
|       } | 
|       return element; | 
|     } | 
|   }, | 
|   | 
|   beforeDestroy() { | 
|     this.popperVM && this.popperVM.$destroy(); | 
|   }, | 
|   | 
|   destroyed() { | 
|     const reference = this.referenceElm; | 
|     if (reference.nodeType === 1) { | 
|       off(reference, 'mouseenter', this.show); | 
|       off(reference, 'mouseleave', this.hide); | 
|       off(reference, 'focus', this.handleFocus); | 
|       off(reference, 'blur', this.handleBlur); | 
|       off(reference, 'click', this.removeFocusing); | 
|     } | 
|   } | 
| }; |