Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(tooltip): add appendTo option to allow customizing tooltip container #18436

Merged
merged 19 commits into from
Sep 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 36 additions & 25 deletions src/component/tooltip/TooltipHTMLContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* under the License.
*/

import { isString, indexOf, each, bind, isArray, isDom } from 'zrender/src/core/util';
import { isString, indexOf, each, bind, isFunction, isArray, isDom } from 'zrender/src/core/util';
import { normalizeEvent } from 'zrender/src/core/event';
import { transformLocalCoord } from 'zrender/src/core/dom';
import env from 'zrender/src/core/env';
Expand Down Expand Up @@ -212,14 +212,20 @@ function assembleCssText(tooltipModel: Model<TooltipOption>, enableTransition?:
}

// If not able to make, do not modify the input `out`.
function makeStyleCoord(out: number[], zr: ZRenderType, appendToBody: boolean, zrX: number, zrY: number) {
function makeStyleCoord(
out: number[],
zr: ZRenderType,
container: HTMLElement | null | undefined,
zrX: number,
zrY: number
) {
const zrPainter = zr && zr.painter;

if (appendToBody) {
if (container) {
const zrViewportRoot = zrPainter && zrPainter.getViewportRoot();
if (zrViewportRoot) {
// Some APPs might use scale on body, so we support CSS transform here.
transformLocalCoord(out, zrViewportRoot, document.body, zrX, zrY);
transformLocalCoord(out, zrViewportRoot, container, zrX, zrY);
viking7982 marked this conversation as resolved.
Show resolved Hide resolved
}
}
else {
Expand All @@ -241,23 +247,22 @@ function makeStyleCoord(out: number[], zr: ZRenderType, appendToBody: boolean, z

interface TooltipContentOption {
/**
* `false`: the DOM element will be inside the container. Default value.
* `true`: the DOM element will be appended to HTML body, which avoid
* some overflow clip but intrude outside of the container.
* Specify target container of the tooltip element.
* Can either be an HTMLElement, CSS selector string, or a function that returns an HTMLElement.
*/
appendToBody: boolean
appendTo: ((chartContainer: HTMLElement) => HTMLElement | undefined | null) | HTMLElement | string
}

class TooltipHTMLContent {

el: HTMLDivElement;

private _container: HTMLElement;
private _api: ExtensionAPI;
private _container: HTMLElement | undefined | null;
plainheart marked this conversation as resolved.
Show resolved Hide resolved

private _show: boolean = false;

private _styleCoord: [number, number, number, number] = [0, 0, 0, 0];
private _appendToBody: boolean;

private _enterable = true;
private _zr: ZRenderType;
Expand All @@ -278,7 +283,6 @@ class TooltipHTMLContent {
private _longHideTimeout: number;

constructor(
container: HTMLElement,
api: ExtensionAPI,
opt: TooltipContentOption
) {
Expand All @@ -291,17 +295,21 @@ class TooltipHTMLContent {
(el as any).domBelongToZr = true;
this.el = el;
const zr = this._zr = api.getZr();
const appendToBody = this._appendToBody = opt && opt.appendToBody;

makeStyleCoord(this._styleCoord, zr, appendToBody, api.getWidth() / 2, api.getHeight() / 2);
const appendTo = opt.appendTo;
const container: HTMLElement | null | undefined = appendTo && (
isString(appendTo)
? document.querySelector(appendTo)
: isDom(appendTo)
? appendTo
: isFunction(appendTo) && appendTo(api.getDom())
);
viking7982 marked this conversation as resolved.
Show resolved Hide resolved

if (appendToBody) {
document.body.appendChild(el);
}
else {
container.appendChild(el);
}
makeStyleCoord(this._styleCoord, zr, container, api.getWidth() / 2, api.getHeight() / 2);

(container || api.getDom()).appendChild(el);

this._api = api;
this._container = container;

// FIXME
Expand Down Expand Up @@ -350,11 +358,13 @@ class TooltipHTMLContent {
update(tooltipModel: Model<TooltipOption>) {
// FIXME
// Move this logic to ec main?
const container = this._container;
const position = getComputedStyle(container, 'position');
const domStyle = container.style;
if (domStyle.position !== 'absolute' && position !== 'absolute') {
domStyle.position = 'relative';
if (!this._container) {
const container = this._api.getDom();
const position = getComputedStyle(container, 'position');
const domStyle = container.style;
if (domStyle.position !== 'absolute' && position !== 'absolute') {
domStyle.position = 'relative';
}
}

// move tooltip if chart resized
Expand Down Expand Up @@ -456,7 +466,7 @@ class TooltipHTMLContent {

moveTo(zrX: number, zrY: number) {
const styleCoord = this._styleCoord;
makeStyleCoord(styleCoord, this._zr, this._appendToBody, zrX, zrY);
makeStyleCoord(styleCoord, this._zr, this._container, zrX, zrY);

if (styleCoord[0] != null && styleCoord[1] != null) {
const style = this.el.style;
Expand Down Expand Up @@ -511,6 +521,7 @@ class TooltipHTMLContent {

dispose() {
this.el.parentNode.removeChild(this.el);
this.el = this._container = null;
}

}
Expand Down
12 changes: 9 additions & 3 deletions src/component/tooltip/TooltipModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,19 @@ export interface TooltipOption extends CommonTooltipOption<TopLevelFormatterPara
renderMode?: 'auto' | TooltipRenderMode // TODO richText renamed canvas?

/**
* If append popup dom to document.body
* Only available when renderMode is html
* @deprecated
* use appendTo: 'body' instead
*/
appendToBody?: boolean
viking7982 marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the implementation of appendToBody is totally removed from the source code, it's better to remove this option instead of making it deprecated. This should be fixed in the future versions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@plainheart OK. Thanks for correcting.


/**
* specified class name of tooltip dom
* If append the tooltip element to another DOM element.
* Only available when renderMode is html
*/
appendTo?: ((chartContainer: HTMLElement) => HTMLElement | undefined | null) | string | HTMLElement

/**
* Specify the class name of tooltip element
* Only available when renderMode is html
*/
className?: string
Expand Down
4 changes: 2 additions & 2 deletions src/component/tooltip/TooltipView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,8 @@ class TooltipView extends ComponentView {

this._tooltipContent = renderMode === 'richText'
? new TooltipRichContent(api)
: new TooltipHTMLContent(api.getDom(), api, {
appendToBody: tooltipModel.get('appendToBody', true)
: new TooltipHTMLContent(api, {
appendTo: tooltipModel.get('appendToBody', true) ? 'body' : tooltipModel.get('appendTo', true)
});
}

Expand Down
Loading