devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
452 lines (447 loc) • 16.4 kB
JavaScript
/**
* DevExtreme (viz/core/tooltip.js)
* Version: 20.1.7
* Build date: Tue Aug 25 2020
*
* Copyright (c) 2012 - 2020 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
"use strict";
var _dom_adapter = require("../../core/dom_adapter");
var _dom_adapter2 = _interopRequireDefault(_dom_adapter);
var _window = require("../../core/utils/window");
var _window2 = _interopRequireDefault(_window);
var _inflector = require("../../core/utils/inflector");
var _inflector2 = _interopRequireDefault(_inflector);
var _renderer = require("../../core/renderer");
var _renderer2 = _interopRequireDefault(_renderer);
var _renderer3 = require("./renderers/renderer");
var _renderer4 = _interopRequireDefault(_renderer3);
var _type = require("../../core/utils/type");
var _type2 = _interopRequireDefault(_type);
var _extend = require("../../core/utils/extend");
var _utils = require("./utils");
var _utils2 = _interopRequireDefault(_utils);
var _format_helper = require("../../format_helper");
var _plaque = require("./plaque");
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
"default": obj
}
}
var mathCeil = Math.ceil;
var mathMax = Math.max;
var mathMin = Math.min;
var window = _window2.default.getWindow();
var DEFAULT_HTML_GROUP_WIDTH = 3e3;
function hideElement($element) {
$element.css({
left: "-9999px"
}).detach()
}
function getSpecialFormatOptions(options, specialFormat) {
var result = options;
switch (specialFormat) {
case "argument":
result = {
format: options.argumentFormat
};
break;
case "percent":
result = {
format: {
type: "percent",
precision: options.format && options.format.percentPrecision
}
}
}
return result
}
function Tooltip(params) {
var that = this;
var renderer;
that._eventTrigger = params.eventTrigger;
that._widgetRoot = params.widgetRoot;
that._widget = params.widget;
that._wrapper = (0, _renderer2.default)("<div>").css({
position: "absolute",
overflow: "hidden",
pointerEvents: "none"
}).addClass(params.cssClass);
that._renderer = renderer = new _renderer4.default.Renderer({
pathModified: params.pathModified,
container: that._wrapper[0]
});
var root = renderer.root;
root.attr({
"pointer-events": "none"
});
that._text = renderer.text(void 0, 0, 0);
that._textGroupHtml = (0, _renderer2.default)("<div>").css({
position: "absolute",
padding: 0,
margin: 0,
border: "0px solid transparent"
}).appendTo(that._wrapper);
that._textHtml = (0, _renderer2.default)("<div>").css({
position: "relative",
display: "inline-block",
padding: 0,
margin: 0,
border: "0px solid transparent"
}).appendTo(that._textGroupHtml)
}
Tooltip.prototype = {
constructor: Tooltip,
dispose: function() {
this._wrapper.remove();
this._renderer.dispose();
this._options = this._widgetRoot = null
},
_getContainer: function() {
var options = this._options;
var container = (0, _renderer2.default)(this._widgetRoot).closest(options.container);
if (0 === container.length) {
container = (0, _renderer2.default)(options.container)
}
return (container.length ? container : (0, _renderer2.default)("body")).get(0)
},
setTemplate: function(contentTemplate) {
var that = this;
that._template = contentTemplate ? that._widget._getTemplate(contentTemplate) : null
},
setOptions: function(options) {
var _this = this;
options = options || {};
var that = this;
that._options = options;
that._textFontStyles = _utils2.default.patchFontOptions(options.font);
that._textFontStyles.color = that._textFontStyles.fill;
that._wrapper.css({
zIndex: options.zIndex
});
that._customizeTooltip = options.customizeTooltip;
var textGroupHtml = that._textGroupHtml;
var textHtml = that._textHtml;
if (this.plaque) {
this.plaque.clear()
}
this.setTemplate(options.contentTemplate);
var pointerEvents = options.interactive ? "auto" : "none";
if (options.interactive) {
this._renderer.root.css({
"-ms-user-select": "auto",
"-moz-user-select": "auto",
"-webkit-user-select": "auto"
})
}
var drawTooltip = function(tooltip, group) {
var state = tooltip._state;
var template = tooltip._template;
var useTemplate = template && !state.formatObject.skipTemplate;
if (state.html || useTemplate) {
if (!state.isRendered) {
if (useTemplate) {
template.render({
model: state.formatObject,
container: textHtml
});
state.html = textHtml.html();
if (!state.html) {
_this.plaque.clear();
return
}
} else {
that._text.attr({
text: ""
});
textHtml.html(state.html)
}
textGroupHtml.css({
color: state.textColor,
width: DEFAULT_HTML_GROUP_WIDTH,
pointerEvents: pointerEvents
});
state.isRendered = true
}
} else {
that._text.css({
fill: state.textColor
}).attr({
text: state.text,
"class": options.cssClass,
"pointer-events": pointerEvents
}).append(group.attr({
align: options.textAlignment
}))
}
tooltip.plaque.customizeCloud({
fill: state.color,
stroke: state.borderColor,
"pointer-events": pointerEvents
})
};
this.plaque = new _plaque.Plaque({
opacity: that._options.opacity,
color: that._options.color,
border: that._options.border,
paddingLeftRight: that._options.paddingLeftRight,
paddingTopBottom: that._options.paddingTopBottom,
arrowLength: that._options.arrowLength,
arrowWidth: 20,
shadow: that._options.shadow,
cornerRadius: that._options.cornerRadius
}, that, that._renderer.root, drawTooltip, true, function(tooltip, g) {
var state = tooltip._state;
if (state.html) {
var bBox;
var getComputedStyle = window.getComputedStyle;
if (getComputedStyle) {
bBox = getComputedStyle(textHtml.get(0));
bBox = {
x: 0,
y: 0,
width: mathCeil(parseFloat(bBox.width)),
height: mathCeil(parseFloat(bBox.height))
}
} else {
bBox = textHtml.get(0).getBoundingClientRect();
bBox = {
x: 0,
y: 0,
width: mathCeil(bBox.width ? bBox.width : bBox.right - bBox.left),
height: mathCeil(bBox.height ? bBox.height : bBox.bottom - bBox.top)
}
}
return bBox
}
return g.getBBox()
}, function(tooltip, g, x, y) {
var state = tooltip._state;
if (state.html) {
that._textGroupHtml.css({
left: x,
top: y
})
} else {
g.move(x, y)
}
});
return that
},
setRendererOptions: function(options) {
this._renderer.setOptions(options);
this._textGroupHtml.css({
direction: options.rtl ? "rtl" : "ltr"
});
return this
},
render: function() {
var that = this;
hideElement(that._wrapper);
var normalizedCSS = {};
for (var name in that._textFontStyles) {
normalizedCSS[_inflector2.default.camelize(name)] = that._textFontStyles[name]
}
that._textGroupHtml.css(normalizedCSS);
that._text.css(that._textFontStyles);
that._eventData = null;
return that
},
update: function(options) {
return this.setOptions(options).render()
},
_prepare: function(formatObject, state) {
var customizeTooltip = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : this._customizeTooltip;
var options = this._options;
var customize = {};
if (_type2.default.isFunction(customizeTooltip)) {
customize = customizeTooltip.call(formatObject, formatObject);
customize = _type2.default.isPlainObject(customize) ? customize : {};
if ("text" in customize) {
state.text = _type2.default.isDefined(customize.text) ? String(customize.text) : ""
}
if ("html" in customize) {
state.html = _type2.default.isDefined(customize.html) ? String(customize.html) : ""
}
}
if (!("text" in state) && !("html" in state)) {
state.text = formatObject.valueText || formatObject.description || ""
}
state.color = customize.color || options.color;
state.borderColor = customize.borderColor || (options.border || {}).color;
state.textColor = customize.fontColor || (this._textFontStyles || {}).color;
return !!state.text || !!state.html || !!this._template
},
show: function(formatObject, params, eventData, customizeTooltip) {
var that = this;
var state = {
formatObject: formatObject
};
if (!that._prepare(formatObject, state, customizeTooltip)) {
return false
}
that._state = state;
that._wrapper.appendTo(that._getContainer());
that._clear();
this.plaque.clear().draw((0, _extend.extend)({}, that._options, {
canvas: that._getCanvas()
}, state, {
x: params.x,
y: params.y,
offset: params.offset
}));
that.moveWrapper();
that._eventData && that._eventTrigger("tooltipHidden", that._eventData);
that._eventData = eventData;
that._eventTrigger("tooltipShown", that._eventData);
return true
},
hide: function() {
var that = this;
hideElement(that._wrapper);
if (that._eventData) {
that._eventTrigger("tooltipHidden", that._eventData);
that._clear();
that._eventData = null
}
},
_clear: function() {
this._textHtml.empty()
},
move: function(x, y, offset) {
this.plaque.draw({
x: x,
y: y,
offset: offset,
canvas: this._getCanvas()
});
this.moveWrapper()
},
moveWrapper: function() {
var that = this;
var plaqueBBox = this.plaque.getBBox();
that._renderer.resize(plaqueBBox.width, plaqueBBox.height);
var offset = that._wrapper.css({
left: 0,
top: 0
}).offset();
var left = plaqueBBox.x;
var top = plaqueBBox.y;
that._wrapper.css({
left: left - offset.left,
top: top - offset.top
});
this.plaque.moveRoot(-left, -top);
if (this._state.html) {
that._textHtml.css({
left: -left,
top: -top
});
that._textGroupHtml.css({
width: plaqueBBox.width
})
}
},
formatValue: function(value, _specialFormat) {
var options = _specialFormat ? getSpecialFormatOptions(this._options, _specialFormat) : this._options;
return (0, _format_helper.format)(value, options.format)
},
getLocation: function() {
return _utils2.default.normalizeEnum(this._options.location)
},
isEnabled: function() {
return !!this._options.enabled
},
isShared: function() {
return !!this._options.shared
},
_getCanvas: function() {
var container = this._getContainer();
var containerBox = container.getBoundingClientRect();
var html = _dom_adapter2.default.getDocumentElement();
var document = _dom_adapter2.default.getDocument();
var left = window.pageXOffset || html.scrollLeft || 0;
var top = window.pageYOffset || html.scrollTop || 0;
var box = {
left: left,
top: top,
width: html.clientWidth + left || 0,
height: mathMax(document.body.scrollHeight, html.scrollHeight, document.body.offsetHeight, html.offsetHeight, document.body.clientHeight, html.clientHeight) || 0,
right: 0,
bottom: 0
};
if (container !== _dom_adapter2.default.getBody()) {
left = mathMax(box.left, box.left + containerBox.left);
top = mathMax(box.top, box.top + containerBox.top);
box.width = mathMin(containerBox.width, box.width) + left + box.left;
box.height = mathMin(containerBox.height, box.height) + top + box.top;
box.left = left;
box.top = top
}
return box
}
};
exports.Tooltip = Tooltip;
exports.plugin = {
name: "tooltip",
init: function() {
this._initTooltip()
},
dispose: function() {
this._disposeTooltip()
},
members: {
_initTooltip: function() {
this._tooltip = new exports.Tooltip({
cssClass: this._rootClassPrefix + "-tooltip",
eventTrigger: this._eventTrigger,
pathModified: this.option("pathModified"),
widgetRoot: this.element(),
widget: this
})
},
_disposeTooltip: function() {
this._tooltip.dispose();
this._tooltip = null
},
_setTooltipRendererOptions: function() {
this._tooltip.setRendererOptions(this._getRendererOptions())
},
_setTooltipOptions: function() {
this._tooltip.update(this._getOption("tooltip"))
}
},
extenders: {
_stopCurrentHandling: function() {
this._tooltip && this._tooltip.hide()
}
},
customize: function(constructor) {
var proto = constructor.prototype;
proto._eventsMap.onTooltipShown = {
name: "tooltipShown"
};
proto._eventsMap.onTooltipHidden = {
name: "tooltipHidden"
};
constructor.addChange({
code: "TOOLTIP_RENDERER",
handler: function() {
this._setTooltipRendererOptions()
},
isThemeDependent: true,
isOptionChange: true
});
constructor.addChange({
code: "TOOLTIP",
handler: function() {
this._setTooltipOptions()
},
isThemeDependent: true,
isOptionChange: true,
option: "tooltip"
})
},
fontFields: ["tooltip.font"]
};