UNPKG

6.3 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_min_1 = __importDefault(require("plotly.js/dist/plotly.min"));
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_min_1.default.react(this.node, data, layout, config).then(plot => {
104 this.showGraph();
105 this.hideImage();
106 this.update();
107 if (frames) {
108 plotly_min_1.default.addFrames(this.node, frames);
109 }
110 if (this.node.offsetWidth > 0 && this.node.offsetHeight > 0) {
111 plotly_min_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_min_1.default.redraw(this.node).then(() => {
153 plotly_min_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;