import { NgZone } from '@angular/core'; import { tooltips } from './tooltip-list'; import { getScrollParent } from './utils/scrollInfo'; const tooltipStyles = { minWidth: '70px', position: 'absolute', padding: '4px 8px', textAlign: 'center', backgroundColor: 'rgba(0,0,0,0.7)', color: '#fff', cursor: 'default', borderRadius: '4px', fontSize: '12px', top: '-9999px', visibility: 'hidden', 'z-index': '9999' }; export class Tooltip { quill: any; toolbar: any; buttons: any; tip: any; selectors: any; mouseenterHandler: any; mouseleaveHandler: any; timeout: any; scrollElm: any; constructor(quill, private ngZone: NgZone) { this.quill = quill; this.toolbar = quill.getModule('toolbar'); this.buttons = null; this.selectors = null; this.tip = null; this.timeout = null; this.mouseenterHandler = null; this.mouseleaveHandler = null; const toolbarElement = this.toolbar.container; if (toolbarElement) { // 添加处理事件 this.buttons = toolbarElement.querySelectorAll('button'); this.selectors = toolbarElement.querySelectorAll('.ql-picker'); for (let el of this.buttons) { this.addHandler(el); } for (let el of this.selectors) { this.addHandler(el); } // 创建tooltip this.createTooltip(); // 滚动元素增加handler this.scrollElm = getScrollParent(toolbarElement); this.scrollElm.addEventListener('scroll', this.mouseleaveHandler); } } createTooltip() { this.tip = document.createElement('div'); this.tip.classList.add('quill-tooltip'); Object.assign(this.tip.style, tooltipStyles); document.body.appendChild(this.tip); } addHandler(el) { this.mouseenterHandler = () => { // this.ngZone.runOutsideAngular(() => { // this.timeout = setTimeout(() => { // this.showTooltip(el); // }, 100); // }); this.timeout = setTimeout(() => { this.showTooltip(el); }, 100); }; this.mouseleaveHandler = () => { if (this.timeout) { // this.ngZone.runOutsideAngular(() => { // clearTimeout(this.timeout); // }); clearTimeout(this.timeout); } this.hideTooltip(); }; // if (this.ngZone && this.ngZone.runOutsideAngular) { // this.ngZone.runOutsideAngular(() => { // el.addEventListener('mouseenter', this.mouseenterHandler); // el.addEventListener('mouseleave', this.mouseleaveHandler); // }); // } el.addEventListener('mouseenter', this.mouseenterHandler); el.addEventListener('mouseleave', this.mouseleaveHandler); } showTooltip(el) { // let format = el.className.replace('ql-', '') const format = [].find .call(el.classList, className => { return className.indexOf('ql-') === 0; }) .replace('ql-', ''); if (tooltips[format]) { const tool = tooltips[format]; if (typeof tool === 'string') { this.tip.textContent = tool; } else { const value = el.value || ''; if (value != null && tool[value]) { this.tip.textContent = tool[value]; } } const elRect = el.getBoundingClientRect(); const tipRect = this.tip.getBoundingClientRect(); const body = document.documentElement || document.body; const bodyRect = { width: body.scrollWidth, height: body.scrollHeight, scrollTop: body.scrollTop, scrollLeft: body.scrollLeft }; const offset = 3; Object.assign(this.tip.style, { top: elRect.top - elRect.height - offset + bodyRect.scrollTop + 'px', left: elRect.left - (tipRect.width - elRect.width) / 2 + bodyRect.scrollLeft + 'px', visibility: 'visible' }); } } hideTooltip() { Object.assign(this.tip.style, { top: '-9999px', visibility: 'hidden' }); } onDestroy() { console.warn('ondestroy'); this.destroyTooltip(); if (this.buttons) { for (let el of this.buttons) { this.removeHandler(el); } } if (this.selectors) { for (let el of this.selectors) { this.removeHandler(el); } } if (this.scrollElm) { this.scrollElm.removeEventListener('scroll', this.mouseleaveHandler); } } destroyTooltip() { if (this.tip.parentNode) { this.tip.parentNode.removeChild(this.tip); } } removeHandler(el) { el.removeEventListener('mouseenter', this.mouseenterHandler); el.removeEventListener('mouseleave', this.mouseleaveHandler); } }