Add JsFunction for tooltip/label formatter callbacks (closes #86)#105
Merged
Conversation
ECharts on the JS side accepts string templates ("{b}: {c}") *or* a
function (params) => string for fields like tooltip.formatter,
label.formatter, axisLabel.formatter, visualMap.formatter, etc. The
string form already worked through the existing setFormatter(String)
overloads; the function form was unreachable because Gson quoted any
Object value as a JSON string.
This adds a JsFunction value class plus a low-level Gson TypeAdapter
that uses JsonWriter.jsonValue(String) to write the body straight
into the output stream, unquoted. Result: when the option JSON is
embedded into the rendered <script> tag (Engine uses Handlebars
triple-braces), the function survives as a real JS callable.
Usage — pass through any existing setFormatter(Object) overload:
tooltip.setFormatter((Object) new JsFunction(
"function (p) { return p.name + ': ' + p.value + ' (' + p.percent + '%)'; }"));
The adapter is registered automatically inside EChartsSerializer's
constructor — no new public surface beyond the JsFunction class itself.
Tests (18 new, all passing):
- JsFunctionTest covers the value class (equals/hashCode/null-rejection),
unquoted-output invariant, multi-line bodies, HTML <tag> preservation
(HTML escaping must stay disabled for raw JS), end-to-end through
Tooltip on both Pie and Bar, sanity check that string formatters
remain quoted, and the read direction (best-effort symmetric path)
- JsFunctionTooltipDemo writes /tmp/js-function-tooltip-demo.html with
a styled Pie chart whose tooltip uses the exact JS shape from the
issue (params.marker / name / value / percent)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
incandescentxxc
approved these changes
May 13, 2026
This was referenced May 14, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #86 — adds the ability to define a tooltip (or label / axis-label / visualMap) formatter as a real JavaScript function built in Java, matching the JS API shown in the issue:
The string-template form (
"{b}: {c}") already worked through the existingsetFormatter(String)overloads. The function form was unreachable because Gson serialized anyObjectformatter as a quoted JSON string — the rendered HTML would contain a string, not a callable function.How it works
A new
JsFunctionvalue class wraps a JS body. A low-level GsonTypeAdapterusesJsonWriter#jsonValue(String)to emit the body straight into the output stream, unquoted. When the option JSON is dropped into the rendered<script>tag (Engineuses Handlebars triple-braces, so no HTML-escaping), the function survives as a real JS callable.The adapter is registered automatically in
EChartsSerializer's constructor — no new public surface beyondJsFunctionitself.How to use
The
(Object)cast picks the existingsetFormatter(Object)overload oversetFormatter(String). Same pattern works onSeriesLabel,AxisLabelvariants,PieLabel, and any other class with anObject-typed formatter.For multi-line bodies just concatenate strings — newlines are preserved verbatim:
Tests added (18 new, all passing)
serializer/JsFunctionTestcovers:<tag>characters preserved (HTML escaping stays disabled, critical for tooltip markup)f(function), not"Visual demo
src/test/java/org/icepear/echarts/demo/JsFunctionTooltipDemo.javabuilds a richer multi-element tooltip (usingparams.marker,params.name,params.value,params.percent) on a Pie chart and writes a self-contained dark-themed HTML to/tmp/js-function-tooltip-demo.html.Test plan
mvn test -Dtest=JsFunctionTest— 18/18 passmvn test -Dtest=JsFunctionTooltipDemo— writes demo fileopen /tmp/js-function-tooltip-demo.html— tooltip renders with rich HTML on hover; verified the rendered HTML contains"formatter":function (params) {(unquoted)mvn test(full suite) — 95 tests, only the 3 pre-existing polar/float-precision failures remain onmasterCleanShot.2026-05-10.at.21.58.37.mp4