UNPKG

6.28 kBJavaScriptView Raw
1"use strict";
2// Copyright (c) Jupyter Development Team.
3// Distributed under the terms of the Modified BSD License.
4var __importDefault = (this && this.__importDefault) || function (mod) {
5 return (mod && mod.__esModule) ? mod : { "default": mod };
6};
7Object.defineProperty(exports, "__esModule", { value: true });
8const widgets_1 = require("@lumino/widgets");
9const plotly_1 = __importDefault(require("plotly.js/dist/plotly"));
10require("../style/index.css");
11/**
12 * The CSS class to add to the Plotly Widget.
13 */
14const CSS_CLASS = "jp-RenderedPlotly";
15/**
16 * The CSS class for a Plotly icon.
17 */
18const CSS_ICON_CLASS = "jp-MaterialIcon jp-PlotlyIcon";
19/**
20 * The MIME type for Plotly.
21 * The version of this follows the major version of Plotly.
22 */
23exports.MIME_TYPE = "application/vnd.plotly.v1+json";
24class RenderedPlotly extends widgets_1.Widget {
25 /**
26 * Create a new widget for rendering Plotly.
27 */
28 constructor(options) {
29 super();
30 this.addClass(CSS_CLASS);
31 this._mimeType = options.mimeType;
32 // Create image element
33 this._img_el = document.createElement("img");
34 this._img_el.className = "plot-img";
35 this.node.appendChild(this._img_el);
36 // Install image hover callback
37 this._img_el.addEventListener("mouseenter", (event) => {
38 this.createGraph(this._model);
39 });
40 }
41 /**
42 * Render Plotly into this widget's node.
43 */
44 renderModel(model) {
45 if (this.hasGraphElement()) {
46 // We already have a graph, don't overwrite it
47 return Promise.resolve();
48 }
49 // Save off reference to model so that we can regenerate the plot later
50 this._model = model;
51 // Check for PNG data in mime bundle
52 const png_data = model.data["image/png"];
53 if (png_data !== undefined && png_data !== null) {
54 // We have PNG data, use it
55 this.updateImage(png_data);
56 return Promise.resolve();
57 }
58 else {
59 // Create a new graph
60 return this.createGraph(model);
61 }
62 }
63 hasGraphElement() {
64 // Check for the presence of the .plot-container element that plotly.js
65 // places at the top of the figure structure
66 return this.node.querySelector(".plot-container") !== null;
67 }
68 updateImage(png_data) {
69 this.hideGraph();
70 this._img_el.src = "data:image/png;base64," + png_data;
71 this.showImage();
72 }
73 hideGraph() {
74 // Hide the graph if there is one
75 let el = this.node.querySelector(".plot-container");
76 if (el !== null && el !== undefined) {
77 el.style.display = "none";
78 }
79 }
80 showGraph() {
81 // Show the graph if there is one
82 let el = this.node.querySelector(".plot-container");
83 if (el !== null && el !== undefined) {
84 el.style.display = "block";
85 }
86 }
87 hideImage() {
88 // Hide the image element
89 let el = this.node.querySelector(".plot-img");
90 if (el !== null && el !== undefined) {
91 el.style.display = "none";
92 }
93 }
94 showImage() {
95 // Show the image element
96 let el = this.node.querySelector(".plot-img");
97 if (el !== null && el !== undefined) {
98 el.style.display = "block";
99 }
100 }
101 createGraph(model) {
102 const { data, layout, frames, config } = model.data[this._mimeType];
103 return plotly_1.default.react(this.node, data, layout, config).then((plot) => {
104 this.showGraph();
105 this.hideImage();
106 this.update();
107 if (frames) {
108 plotly_1.default.addFrames(this.node, frames);
109 }
110 if (this.node.offsetWidth > 0 && this.node.offsetHeight > 0) {
111 plotly_1.default.toImage(plot, {
112 format: "png",
113 width: this.node.offsetWidth,
114 height: this.node.offsetHeight,
115 }).then((url) => {
116 const imageData = url.split(",")[1];
117 if (model.data["image/png"] !== imageData) {
118 model.setData({
119 data: Object.assign(Object.assign({}, model.data), { "image/png": imageData }),
120 });
121 }
122 });
123 }
124 // Handle webgl context lost events
125 this.node.on("plotly_webglcontextlost", () => {
126 const png_data = model.data["image/png"];
127 if (png_data !== undefined && png_data !== null) {
128 // We have PNG data, use it
129 this.updateImage(png_data);
130 return Promise.resolve();
131 }
132 });
133 });
134 }
135 /**
136 * A message handler invoked on an `'after-show'` message.
137 */
138 onAfterShow(msg) {
139 this.update();
140 }
141 /**
142 * A message handler invoked on a `'resize'` message.
143 */
144 onResize(msg) {
145 this.update();
146 }
147 /**
148 * A message handler invoked on an `'update-request'` message.
149 */
150 onUpdateRequest(msg) {
151 if (this.isVisible && this.hasGraphElement()) {
152 plotly_1.default.redraw(this.node).then(() => {
153 plotly_1.default.Plots.resize(this.node);
154 });
155 }
156 }
157}
158exports.RenderedPlotly = RenderedPlotly;
159/**
160 * A mime renderer factory for Plotly data.
161 */
162exports.rendererFactory = {
163 safe: true,
164 mimeTypes: [exports.MIME_TYPE],
165 createRenderer: (options) => new RenderedPlotly(options),
166};
167const extensions = [
168 {
169 id: "@jupyterlab/plotly-extension:factory",
170 rendererFactory: exports.rendererFactory,
171 rank: 0,
172 dataType: "json",
173 fileTypes: [
174 {
175 name: "plotly",
176 mimeTypes: [exports.MIME_TYPE],
177 extensions: [".plotly", ".plotly.json"],
178 iconClass: CSS_ICON_CLASS,
179 },
180 ],
181 documentWidgetFactoryOptions: {
182 name: "Plotly",
183 primaryFileType: "plotly",
184 fileTypes: ["plotly", "json"],
185 defaultFor: ["plotly"],
186 },
187 },
188];
189exports.default = extensions;