1 |
|
2 |
|
3 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
4 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
5 | return new (P || (P = Promise))(function (resolve, reject) {
|
6 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
7 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
8 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
9 | step((generator = generator.apply(thisArg, _arguments || [])).next());
|
10 | });
|
11 | };
|
12 | import { Widget } from "@lumino/widgets";
|
13 | import "../style/index.css";
|
14 |
|
15 |
|
16 |
|
17 | const CSS_CLASS = "jp-RenderedPlotly";
|
18 |
|
19 |
|
20 |
|
21 | const CSS_ICON_CLASS = "jp-MaterialIcon jp-PlotlyIcon";
|
22 |
|
23 |
|
24 |
|
25 |
|
26 | export const MIME_TYPE = "application/vnd.plotly.v1+json";
|
27 | export class RenderedPlotly extends Widget {
|
28 | |
29 |
|
30 |
|
31 | constructor(options) {
|
32 | super();
|
33 | this.addClass(CSS_CLASS);
|
34 | this._mimeType = options.mimeType;
|
35 |
|
36 | this._img_el = document.createElement("img");
|
37 | this._img_el.className = "plot-img";
|
38 | this.node.appendChild(this._img_el);
|
39 |
|
40 | this._img_el.addEventListener("mouseenter", (event) => {
|
41 | this.createGraph(this._model);
|
42 | });
|
43 | }
|
44 | |
45 |
|
46 |
|
47 | renderModel(model) {
|
48 | if (this.hasGraphElement()) {
|
49 |
|
50 | return Promise.resolve();
|
51 | }
|
52 |
|
53 | this._model = model;
|
54 |
|
55 | const png_data = model.data["image/png"];
|
56 | if (png_data !== undefined && png_data !== null) {
|
57 |
|
58 | this.updateImage(png_data);
|
59 | return Promise.resolve();
|
60 | }
|
61 | else {
|
62 |
|
63 | return this.createGraph(model);
|
64 | }
|
65 | }
|
66 | hasGraphElement() {
|
67 |
|
68 |
|
69 | return this.node.querySelector(".plot-container") !== null;
|
70 | }
|
71 | updateImage(png_data) {
|
72 | this.hideGraph();
|
73 | this._img_el.src = "data:image/png;base64," + png_data;
|
74 | this.showImage();
|
75 | }
|
76 | hideGraph() {
|
77 |
|
78 | let el = this.node.querySelector(".plot-container");
|
79 | if (el !== null && el !== undefined) {
|
80 | el.style.display = "none";
|
81 | }
|
82 | }
|
83 | showGraph() {
|
84 |
|
85 | let el = this.node.querySelector(".plot-container");
|
86 | if (el !== null && el !== undefined) {
|
87 | el.style.display = "block";
|
88 | }
|
89 | }
|
90 | hideImage() {
|
91 |
|
92 | let el = this.node.querySelector(".plot-img");
|
93 | if (el !== null && el !== undefined) {
|
94 | el.style.display = "none";
|
95 | }
|
96 | }
|
97 | showImage() {
|
98 |
|
99 | let el = this.node.querySelector(".plot-img");
|
100 | if (el !== null && el !== undefined) {
|
101 | el.style.display = "block";
|
102 | }
|
103 | }
|
104 | createGraph(model) {
|
105 | const { data, layout, frames, config } = model.data[this._mimeType];
|
106 |
|
107 | const loadPlotly = () => __awaiter(this, void 0, void 0, function* () {
|
108 | if (RenderedPlotly.Plotly === null) {
|
109 | RenderedPlotly.Plotly = yield import("plotly.js/dist/plotly");
|
110 | RenderedPlotly._resolveLoadingPlotly();
|
111 | }
|
112 | return RenderedPlotly.loadingPlotly;
|
113 | });
|
114 | return loadPlotly()
|
115 | .then(() => RenderedPlotly.Plotly.react(this.node, data, layout, config))
|
116 | .then((plot) => {
|
117 | this.showGraph();
|
118 | this.hideImage();
|
119 | this.update();
|
120 | if (frames) {
|
121 | RenderedPlotly.Plotly.addFrames(this.node, frames);
|
122 | }
|
123 | if (this.node.offsetWidth > 0 && this.node.offsetHeight > 0) {
|
124 | RenderedPlotly.Plotly.toImage(plot, {
|
125 | format: "png",
|
126 | width: this.node.offsetWidth,
|
127 | height: this.node.offsetHeight,
|
128 | }).then((url) => {
|
129 | const imageData = url.split(",")[1];
|
130 | if (model.data["image/png"] !== imageData) {
|
131 | model.setData({
|
132 | data: Object.assign(Object.assign({}, model.data), { "image/png": imageData }),
|
133 | });
|
134 | }
|
135 | });
|
136 | }
|
137 |
|
138 | this.node.on("plotly_webglcontextlost", () => {
|
139 | const png_data = model.data["image/png"];
|
140 | if (png_data !== undefined && png_data !== null) {
|
141 |
|
142 | this.updateImage(png_data);
|
143 | return Promise.resolve();
|
144 | }
|
145 | });
|
146 | });
|
147 | }
|
148 | |
149 |
|
150 |
|
151 | onAfterShow(msg) {
|
152 | this.update();
|
153 | }
|
154 | |
155 |
|
156 |
|
157 | onResize(msg) {
|
158 | this.update();
|
159 | }
|
160 | |
161 |
|
162 |
|
163 | onUpdateRequest(msg) {
|
164 | if (RenderedPlotly.Plotly && this.isVisible && this.hasGraphElement()) {
|
165 | RenderedPlotly.Plotly.redraw(this.node).then(() => {
|
166 | RenderedPlotly.Plotly.Plots.resize(this.node);
|
167 | });
|
168 | }
|
169 | }
|
170 | }
|
171 | RenderedPlotly.Plotly = null;
|
172 | RenderedPlotly.loadingPlotly = new Promise((resolve) => {
|
173 | RenderedPlotly._resolveLoadingPlotly = resolve;
|
174 | });
|
175 |
|
176 |
|
177 |
|
178 | export const rendererFactory = {
|
179 | safe: true,
|
180 | mimeTypes: [MIME_TYPE],
|
181 | createRenderer: (options) => new RenderedPlotly(options),
|
182 | };
|
183 | const extensions = [
|
184 | {
|
185 | id: "@jupyterlab/plotly-extension:factory",
|
186 | rendererFactory,
|
187 | rank: 0,
|
188 | dataType: "json",
|
189 | fileTypes: [
|
190 | {
|
191 | name: "plotly",
|
192 | mimeTypes: [MIME_TYPE],
|
193 | extensions: [".plotly", ".plotly.json"],
|
194 | iconClass: CSS_ICON_CLASS,
|
195 | },
|
196 | ],
|
197 | documentWidgetFactoryOptions: {
|
198 | name: "Plotly",
|
199 | primaryFileType: "plotly",
|
200 | fileTypes: ["plotly", "json"],
|
201 | defaultFor: ["plotly"],
|
202 | },
|
203 | },
|
204 | ];
|
205 | export default extensions;
|