Skip to content

Commit f86985a

Browse files
committed
toggle mathjax via callbacks
1 parent c61b771 commit f86985a

File tree

3 files changed

+86
-30
lines changed

3 files changed

+86
-30
lines changed

components/dash-core-components/src/fragments/Graph.react.js

+31-24
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import lazyLoadMathJax from '../utils/LazyLoader/mathjax';
12
import React, {Component} from 'react';
23
// /build/withPolyfill for IE11 support - https://github.com/maslianok/react-resize-detector/issues/144
34
import ResizeDetector from 'react-resize-detector/build/withPolyfill';
@@ -144,15 +145,15 @@ class PlotlyGraph extends Component {
144145

145146
plot(props) {
146147
let {figure, config} = props;
147-
const {animate, animation_options, responsive} = props;
148+
const {animate, animation_options, responsive, mathjax} = props;
148149

149150
const gd = this.gd.current;
150151
figure = props._dashprivate_transformFigure(figure, gd);
151152
config = props._dashprivate_transformConfig(config, gd);
152153

153154
const configClone = this.getConfig(config, responsive);
154155
// add typesetMath | not exposed to the dash API
155-
configClone.typesetMath = this.props.mathjax;
156+
configClone.typesetMath = mathjax;
156157

157158
const figureClone = {
158159
data: figure.data,
@@ -180,32 +181,34 @@ class PlotlyGraph extends Component {
180181

181182
gd.classList.add('dash-graph--pending');
182183

183-
return Plotly.react(gd, figureClone).then(() => {
184-
const gd = this.gd.current;
184+
return lazyLoadMathJax(mathjax)
185+
.then(() => Plotly.react(gd, figureClone))
186+
.then(() => {
187+
const gd = this.gd.current;
185188

186-
// double-check gd hasn't been unmounted
187-
if (!gd) {
188-
return;
189-
}
189+
// double-check gd hasn't been unmounted
190+
if (!gd) {
191+
return;
192+
}
190193

191-
gd.classList.remove('dash-graph--pending');
194+
gd.classList.remove('dash-graph--pending');
192195

193-
// in case we've made a new DOM element, transfer events
194-
if (this._hasPlotted && gd !== this._prevGd) {
195-
if (this._prevGd && this._prevGd.removeAllListeners) {
196-
this._prevGd.removeAllListeners();
197-
Plotly.purge(this._prevGd);
196+
// in case we've made a new DOM element, transfer events
197+
if (this._hasPlotted && gd !== this._prevGd) {
198+
if (this._prevGd && this._prevGd.removeAllListeners) {
199+
this._prevGd.removeAllListeners();
200+
Plotly.purge(this._prevGd);
201+
}
202+
this._hasPlotted = false;
198203
}
199-
this._hasPlotted = false;
200-
}
201204

202-
if (!this._hasPlotted) {
203-
this.bindEvents();
204-
this.graphResize(true);
205-
this._hasPlotted = true;
206-
this._prevGd = gd;
207-
}
208-
});
205+
if (!this._hasPlotted) {
206+
this.bindEvents();
207+
this.graphResize(true);
208+
this._hasPlotted = true;
209+
this._prevGd = gd;
210+
}
211+
});
209212
}
210213

211214
mergeTraces(props, dataKey, plotlyFnKey) {
@@ -430,6 +433,7 @@ class PlotlyGraph extends Component {
430433
return;
431434
}
432435
if (
436+
this.props.mathjax !== nextProps.mathjax ||
433437
this.props.figure !== nextProps.figure ||
434438
this.props._dashprivate_transformConfig !==
435439
nextProps._dashprivate_transformConfig ||
@@ -453,7 +457,10 @@ class PlotlyGraph extends Component {
453457
}
454458

455459
componentDidUpdate(prevProps) {
456-
if (prevProps.id !== this.props.id) {
460+
if (
461+
prevProps.id !== this.props.id ||
462+
prevProps.mathjax !== this.props.mathjax
463+
) {
457464
this.plot(this.props);
458465
}
459466
}
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
export default () => Promise.resolve(window.MathJax ||
2-
import(/* webpackChunkName: "mathjax" */ 'mathjax/es5/tex-svg.js').then(() => {
3-
window.MathJax.config.startup.typeset = false;
1+
export default (mathjax) => Promise.resolve(window.MathJax || (
2+
mathjax === false ?
3+
undefined :
4+
import(/* webpackChunkName: "mathjax" */ 'mathjax/es5/tex-svg.js').then(() => {
5+
window.MathJax.config.startup.typeset = false;
46

5-
return window.MathJax;
6-
})
7-
);
7+
return window.MathJax;
8+
})
9+
));

components/dash-core-components/tests/integration/graph/test_graph_varia.py

+47
Original file line numberDiff line numberDiff line change
@@ -960,3 +960,50 @@ def test_grva012_with_mathjax(dash_dcc, is_eager):
960960
assert findAsyncMathJax(scripts) is None
961961

962962
assert dash_dcc.get_logs() == []
963+
964+
965+
@pytest.mark.parametrize("is_eager", [True, False])
966+
def test_grva013_toggle_mathjax(dash_dcc, is_eager):
967+
app = Dash(__name__, eager_loading=is_eager)
968+
969+
gravity = "$F=\\frac{Gm_1m_2}{r^2}$"
970+
971+
app.layout = html.Div(
972+
[
973+
html.Button("Toggle MathJax", id="btn"),
974+
dcc.Graph(
975+
id="gd",
976+
figure={
977+
"data": [{"y": [3, 1, 2]}],
978+
"layout": {"title": {"text": gravity}},
979+
},
980+
),
981+
]
982+
)
983+
984+
@app.callback(
985+
Output("gd", "mathjax"), Input("btn", "n_clicks"), prevent_initial_call=True
986+
)
987+
def toggle(n):
988+
return (n or 0) % 2 != 0
989+
990+
dash_dcc.start_server(app)
991+
992+
# Initial state: no MathJax loaded or rendered, unformatted text is shown
993+
dash_dcc.wait_for_contains_text(".gtitle", gravity)
994+
assert not dash_dcc.driver.execute_script("return !!window.MathJax")
995+
996+
btn = dash_dcc.find_element("#btn")
997+
btn.click()
998+
999+
# One click: MathJax is rendered, unformatted text is gone
1000+
1001+
dash_dcc.wait_for_element(".gtitle-math")
1002+
assert dash_dcc.driver.execute_script("return !!window.MathJax")
1003+
1004+
btn.click()
1005+
1006+
# Second click: Back to initial state except that MathJax library is still loaded
1007+
dash_dcc.wait_for_contains_text(".gtitle", gravity)
1008+
dash_dcc.wait_for_no_elements(".gtitle-math")
1009+
assert dash_dcc.driver.execute_script("return !!window.MathJax")

0 commit comments

Comments
 (0)