/**
* Refer to <span color = "yellow">{@link ve.Feature}</span> for methods or fields inherited from the parent, such as automatic destructuring.
*
* Represents a Tooltip Feature that contains a set of components which are wrapped inside an Interface. This uses a {@link tippy} element.
* - Functional binding: <span color=00ffff>veTooltip</span>().
*
* ##### Constructor:
* - `arg0_components_obj`: {@link function}|{@link Object}<{@link ve.Component}>|{@link string}
* - `arg1_options`: {@link Object}
* - `attributes`: {@link Object}<{@link string}>
* - `element`: {@link HTMLElement}|{@link string} - The anchor element that ve.Tooltip should be bound to.
* - `style`: {@linK Object}<{@link string}>
*
* ##### Instance:
* - `.anchor_element`: {@link HTMLElement}
* - `.v`: {@link HTMLElement}
*
* @augments ve.Feature
* @memberof ve.Feature
* @type {ve.Tooltip}
*/
ve.Tooltip = class extends ve.Feature {
constructor (arg0_components_obj, arg1_options) {
//Convert from parameters
let components_obj = arg0_components_obj;
let options = (arg1_options) ? arg1_options : {};
super(components_obj, options);
//Initialise options
if (options.element === undefined)
console.error(`arg1_options.element needs to be defined for ve.Tooltip to work.`);
//Declare local instance variables
this.anchor_element = (typeof options.element === "string") ?
document.querySelector(options.element) : options.element;
this.element = document.createElement("div");
this.element.instance = this;
HTML.setAttributesObject(this.element, (options.attributes) ? options.attributes : {});
HTML.applyTelestyle(this.element, options.style);
if (options.theme)
HTML.applyTelestyle(this.element, ve.registry.themes[options.theme]);
this.v = components_obj;
//Set tippy tooltip based on element
this.tippy = tippy(this.anchor_element, {
allowHTML: true,
appendTo: document.body,
content: this.element,
interactive: false,
offset: (options.offset) ? options.offset : [0, 8],
placement: (options.placement) ? options.placement : "auto"
});
}
/**
* Returns the element of the current tooltip.
* - Method of: {@link ve.Tooltip}
*
* @alias v
* @memberof ve.Feature.ve.Tooltip
* @type {HTMLElement}
*
* @returns {HTMLElement}
*/
get v () {
//Return statement
return this.element;
}
/**
* Sets the value of the current tooltip using a {@link Array}<{@link ve.Component}> type, a string, or a function that returns a string.
* - Method of: {@link ve.Tooltip}
*
* @alias v
* @memberof ve.Feature.ve.Tooltip
* @type {HTMLElement}
*
* @param {function|string|ve.Component[]} arg0_value
*/
set v (arg0_value) {
//Convert from parameters
let components_obj = arg0_value;
//Reset innerHTML
this.element.innerHTML = "";
//Append components_obj if possible
if (typeof components_obj === "function")
components_obj = components_obj(this); //Fetch return value if possible
if (typeof components_obj === "object") {
//Iterate over all components in components_obj
Object.iterate(components_obj, (local_key, local_value) => {
this.element.appendChild(local_value.element);
});
} else if (typeof components_obj === "string") {
this.element.innerHTML = components_obj;
}
}
/**
* Removes any redundant tooltips.
* - Static method of: {@link ve.Tooltip}
*
* @alias #refresh
*/
static refresh () {
for (let i = ve.Feature.instances.length - 1; i >= 0; i--)
if (ve.Feature.instances[i] instanceof ve.Tooltip) {
let local_feature = ve.Feature.instances[i];
if (local_feature.tippy && !document.body.contains(local_feature.tippy.reference)) {
//1. Destroy the Tippy first
local_feature.tippy.destroy();
//2. Delete everything inside the feature
let all_feature_keys = Object.keys(local_feature);
for (let x = 0; x < all_feature_keys.length; x++)
delete local_feature[all_feature_keys[x]];
//3. Purge it from the .instances array
ve.Feature.instances.splice(i, 1);
local_feature = null;
}
}
}
};
//Functional binding
/**
* @returns {ve.Tooltip}
*/
veTooltip = function () {
//Return statement
return new ve.Tooltip(...arguments);
};