由于popper.js这个名字比较大众化,有必要说明一下具体指的是哪一个;
没错就是你想的这个:
https://popper.js.org/tooltip-examples.html
https://github.com/FezVrasta/popper.js
popper 是一个定位引擎,就是说他只做一件事使指定节点定位到指定位置。至于DOM的显示、隐藏、内容、外观、丑美胖瘦……他都不管
那tooltip.js和popper是什么关系呢?
可以说是理论与实践的关系,tooltip是对popper的具体应用。想想是不是很兴奋,什么下拉菜单、select表单模拟、提示工具……总之,一切弹出定位的UI组件都可以通过这个引擎实现。
new Tooltip(element,options);
element
options
选项既可以在js初始化时传入,也可以在元素上通过data-绑定
选项 | 类型 | 说明 | 值 |
---|---|---|---|
placement | String | 弹出位置 | 默认:bottom;top(-start, -end), right(-start, -end), bottom(-start, -end), left(-start, -end) |
arrowSelector | String | 设置三角的class | 默认:.tooltip-arrow, .tooltip__arrow |
innerSelector | String | 设置内容容器的class | 默认:.tooltip-inner, .tooltip__inner |
container | HTMLElement、String、false | 将tooltip元素插入到container元素 | 默认:false (参照元素的父节点) |
delay | Number、Object | 延迟显示或隐藏 ,不适用手动触发类型; | 默认:0;如果是一个值(Number),同时被应用到显示和隐藏;如果是对象{ show: 500, hide: 100 },则分别被应用到显示和隐藏 |
html | Boolean | 把title中的内容以text(false)或者html(true)格式插入到tooltip-inner里 | 默认:false |
template | String | 插入的模板内容 | 默认:
|
title | String、HTMLElement、TitleFunction | 弹出的具体内容title | |
trigger | String | 触发方式:多种触发方式,中间用空格隔开;manual 手动,不能与其他方式组合使用; | 默认:hover focus;可选hover、focus、click、manual |
closeOnClickOutside | Boolean | 是否在点击弹出元素和参照元素以外,关闭弹出元素;只适用于click方式 | 默认:false |
boundariesElement | String、HTMLElement | 设置弹出元素的边界 | |
offset | String、Number | 相对参照元素的偏移量设置 | 默认:0 |
popperOptions | Object | 直接设置popper实例的选项 |
import Popper from 'popper.js';
import isFunction from '../../popper/src/utils/isFunction';
const DEFAULT_OPTIONS = {
container: false,
delay: 0,
html: false,
placement: 'top',
title: '',
template:
'',
trigger: 'hover focus',
offset: 0,
arrowSelector: '.tooltip-arrow, .tooltip__arrow',
innerSelector: '.tooltip-inner, .tooltip__inner',
};
export default class Tooltip {
constructor(reference, options) {
// apply user options over default ones
// 用户选项覆盖默认选项
options = { ...DEFAULT_OPTIONS, ...options };
// 如果是jq对象,取第一个————转成js节点
reference.jquery && (reference = reference[0]);
// cache reference and options
// 缓存参照元素和选项
this.reference = reference;
this.options = options;
// get events list
// 获取触发方式的数组列表
// events 是数组,触发事件的数组
const events =
typeof options.trigger === 'string'
? options.trigger
.split(' ')
.filter(
trigger => ['click', 'hover', 'focus'].indexOf(trigger) !== -1
)
: [];
// set initial state
// 设置出事状态
// 显示或隐藏。默认隐藏
this._isOpen = false;
// Popper实例选项
this._popperOptions = {};
// set event listeners
// 设置事件监听
this._setEventListeners(reference, events, options);
}
//
// Public methods
//
/**
* Reveals an element's tooltip. This is considered a "manual" triggering of the tooltip.
* Tooltips with zero-length titles are never displayed.
* @method Tooltip#show
* @memberof Tooltip
*/
// manual 手动触发
show = () => this._show(this.reference, this.options);
/**
* Hides an element’s tooltip. This is considered a “manual” triggering of the tooltip.
* @method Tooltip#hide
* @memberof Tooltip
*/
// manual 手动触发
hide = () => this._hide();
/**
* Hides and destroys an element’s tooltip.
* @method Tooltip#dispose
* @memberof Tooltip
*/
// manual 手动触发
dispose = () => this._dispose();
/**
* Toggles an element’s tooltip. This is considered a “manual” triggering of the tooltip.
* @method Tooltip#toggle
* @memberof Tooltip
*/
// manual 手动触发
toggle = () => {
if (this._isOpen) {
return this.hide();
} else {
return this.show();
}
};
/**
* Updates the tooltip's title content
* @method Tooltip#updateTitleContent
* @memberof Tooltip
* @param {String|HTMLElement} title - The new content to use for the title
*/
// manual 手动触发
updateTitleContent = (title) => this._updateTitleContent(title);
//
// Private methods
//
// 私有方法列表
_events = [];
/**
* Creates a new tooltip node
* @memberof Tooltip
* @private
* @param {HTMLElement} reference
* @param {String} template
* @param {String|HTMLElement|TitleFunction} title
* @param {Boolean} allowHtml
* @return {HTMLElement} tooltipNode
*/
_create(reference, template, title, allowHtml) {
// create tooltip element
// 创建一个div元素,里面插入template内容
const tooltipGenerator = window.document.createElement('div');
tooltipGenerator.innerHTML = template.trim();
// 获取到模板中的第一个子节点————class=“tooltip”
const tooltipNode = tooltipGenerator.childNodes[0];
// add unique ID to our tooltip (needed for accessibility reasons)
// 给class=“tooltip”添加一个随机ID
tooltipNode.id = `tooltip_${Math.random()
.toString(36)
.substr(2, 10)}`;
// set initial `aria-hidden` state to `false` (it's visible!)
// 设置属性为可见的
tooltipNode.setAttribute('aria-hidden', 'false');
// add title to tooltip
// 获取title节点,————tooltip-inner(现在里面是空的)
const titleNode = tooltipGenerator.querySelector(this.options.innerSelector);
// 给title节点添加内容
this._addTitleContent(reference, title, allowHtml, titleNode);
// return the generated tooltip node
// 返回新创建div里的内容,也就是class tooltip 节点
return tooltipNode;
}
_addTitleContent(reference, title, allowHtml, titleNode) {
if (title.nodeType === 1 || title.nodeType === 11) {
// if title is a element node or document fragment, append it only if allowHtml is true
// 如果title内容是元素节点或者 #document 片段
// 如果option.html=true,允许插入html类型
// 把title内容插入title节点(tooltip-inner)
allowHtml && titleNode.appendChild(title);
} else if (isFunction(title)) {
// if title is a function, call it and set textContent or innerHtml depending by `allowHtml` value
// 如果title是一个函数;
// titleText 调用函数,并且把this指向参照元素,获取title函数的返回值,
const titleText = title.call(reference);
// 如果option.html=true,允许插入html类型--> 则插入title的所有内容;
// 否则插入title中的所有文本,包括