55 < title > Plotly</ title >
66 < link href ="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css " rel ="stylesheet ">
77 < link href ="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css " rel ="stylesheet ">
8- < script src ="https://code.jquery.com/jquery-3.5.1.slim. min.js "> </ script >
8+ < script src ="https://code.jquery.com/jquery-3.5.1.min.js "> </ script >
99 < script src ="https://cdn.plot.ly/plotly-2.32.0.min.js "> </ script >
1010 < style >
1111 body {
12- display : flex;
1312 height : 100vh ;
1413 margin : 0 ;
1514 overflow : hidden;
1615 font-family : Arial, sans-serif;
17- }
18-
19- # sidebar {
20- width : 300px ;
21- padding : 15px ;
22- background-color : # f8f9fa ;
23- overflow-y : auto;
24- flex-shrink : 0 ;
16+ position : relative;
2517 }
2618
2719 .box {
2820 width : 300px ;
29- height : 200 px ;
21+ height : 300 px ;
3022 background-color : # fff ;
31- border : 1px solid dodgerblue ;
23+ border : 1px solid lightblue ;
3224 border-radius : 5px ;
3325 box-shadow : 0 15px 15px lightgrey;
26+ position : absolute;
27+ top : 50px ;
28+ left : 50px ;
29+ resize : both;
30+ overflow : hidden;
31+ z-index : 0 ;
3432 }
3533
3634 .box-header {
3735 color : # fff ;
38- background-color : dodgerblue;
39- padding : 10px 15px ;
36+ padding : 5px 10px ;
37+ display : flex;
38+ justify-content : space-between;
39+ align-items : center;
40+ cursor : pointer;
41+ height : 40px ;
42+ flex-shrink : 0 ;
4043 }
4144
42- .drag-handle {
43- cursor : pointer;
45+ .header-buttons {
46+ display : flex;
47+ gap : 5px ;
48+ flex-shrink : 0 ;
4449 }
4550
46- .box-header {
47- color : # fff ;
48- background-color : dodgerblue;
51+ .box-body {
52+ height : calc (100% - 40px );
53+ padding : 10px ;
54+ overflow : auto;
55+ background-color : lightblue;
56+ }
57+
58+ .btn {
59+ border : 1px solid # ccc ;
4960 padding : 5px 10px ;
61+ background-color : white;
62+ cursor : pointer;
63+ flex-shrink : 0 ;
64+ }
65+
66+ .btn : hover {
67+ background-color : # f0f0f0 ;
68+ }
69+
70+ # add-box-btn {
71+ position : absolute;
72+ top : 10px ;
73+ left : 10px ;
74+ cursor : pointer;
75+ z-index : 1000 ;
76+ color : lightblue;
77+ }
78+
79+ # add-box-btn : hover {
80+ color : lightskyblue;
81+ }
82+
83+ # overlay-text {
84+ position : absolute;
85+ top : 10px ;
86+ left : 50% ;
87+ transform : translateX (-50% );
88+ font-size : 24px ;
89+ color : rgba (0 , 0 , 0 , 0.5 );
90+ pointer-events : none;
91+ z-index : -1000 ;
5092 }
5193 </ style >
5294</ head >
5395< body >
54- < div id ="sidebar ">
55- < h1 > Plotly JSON Visualizer</ h1 >
56- < div >
57- < label for ="json-input "> JSON Data:</ label > < br >
58- < textarea id ="json-input " class ="form-control " rows ="10 "> </ textarea > < br >
59- < label for ="json-path "> JSON Path (optional):</ label > < br >
60- < input type ="text " id ="json-path " class ="form-control " placeholder ="e.g., data.chart "> < br > < br >
61- < button onclick ="reloadPlot() " class ="btn btn-success "> Reload Plot</ button >
62- </ div >
63- </ div >
64- < div class ="box " data-draggable ="true " data-resizable ="true ">
65- < div class ="box-header drag-handle " data-drag-handle ="true "> Drag here</ div >
66- < div class ="box-body " id ="div-plotly "> </ div >
67- </ div >
96+ < i id ="add-box-btn " class ="fas fa-plus-circle fa-2x "> </ i >
97+ < div id ="overlay-text "> Plotly JSON Visualizer</ div >
6898
6999< script >
70- const plotDiv = document . getElementById ( 'div-plotly' ) ;
100+ document . getElementById ( 'add-box-btn' ) . addEventListener ( 'click' , addNewBox ) ;
101+
102+ function addNewBox ( ) {
103+ const box = document . createElement ( 'div' ) ;
104+ box . className = 'box' ;
105+ box . innerHTML = `
106+ <div class="box-header" data-drag-handle="true">
107+ <div class="header-buttons">
108+ <button class="btn btn-generate">Generate</button>
109+ <button class="btn btn-back" style="display:none;">Back</button>
110+ </div>
111+ <span class="btn btn-close">X</span>
112+ </div>
113+ <div class="box-body">
114+ <div class="view-json">
115+ <label for="json-input">JSON Data:</label><br>
116+ <textarea class="json-input form-control" rows="10"></textarea><br>
117+ <button class="btn btn-beautify">Beautify JSON</button><br><br>
118+ <label for="json-path">JSON Path (optional):</label><br>
119+ <input type="text" class="json-path form-control" placeholder="e.g., data.chart"><br><br>
120+ </div>
121+ <div class="view-chart" style="display:none;">
122+ <div class="chart" style="width: 100%; height: 100%;"></div>
123+ </div>
124+ </div>
125+ ` ;
126+ document . body . appendChild ( box ) ;
71127
72- function reloadPlot ( ) {
73- const jsonData = document . getElementById ( 'json-input' ) . value ;
74- const jsonPath = document . getElementById ( 'json-path' ) . value ;
128+ setupDraggable ( box ) ;
129+ setupResizable ( box ) ;
130+ setupZIndex ( box ) ;
131+
132+ box . querySelector ( '.btn-generate' ) . addEventListener ( 'click' , ( ) => reloadPlot ( box ) ) ;
133+ box . querySelector ( '.btn-back' ) . addEventListener ( 'click' , ( ) => switchToJson ( box ) ) ;
134+ box . querySelector ( '.btn-close' ) . addEventListener ( 'click' , ( ) => box . remove ( ) ) ;
135+ box . querySelector ( '.btn-beautify' ) . addEventListener ( 'click' , ( ) => beautifyJson ( box ) ) ;
136+ }
137+
138+ function switchToChart ( box ) {
139+ const viewJson = box . querySelector ( '.view-json' ) ;
140+ const viewChart = box . querySelector ( '.view-chart' ) ;
141+ const btnGenerate = box . querySelector ( '.btn-generate' ) ;
142+ const btnBack = box . querySelector ( '.btn-back' ) ;
143+ viewJson . style . display = 'none' ;
144+ viewChart . style . display = 'block' ;
145+ btnGenerate . style . display = 'none' ;
146+ btnBack . style . display = 'block' ;
147+ updatePlotSize ( box ) ;
148+ }
149+
150+ function switchToJson ( box ) {
151+ const viewJson = box . querySelector ( '.view-json' ) ;
152+ const viewChart = box . querySelector ( '.view-chart' ) ;
153+ const btnGenerate = box . querySelector ( '.btn-generate' ) ;
154+ const btnBack = box . querySelector ( '.btn-back' ) ;
155+ viewJson . style . display = 'block' ;
156+ viewChart . style . display = 'none' ;
157+ btnGenerate . style . display = 'block' ;
158+ btnBack . style . display = 'none' ;
159+ }
160+
161+ function reloadPlot ( box ) {
162+ const jsonData = box . querySelector ( '.json-input' ) . value ;
163+ const jsonPath = box . querySelector ( '.json-path' ) . value ;
75164
76165 try {
77166 let plotData = JSON . parse ( jsonData ) ;
@@ -92,71 +181,89 @@ <h1>Plotly JSON Visualizer</h1>
92181 responsive : true
93182 } ;
94183
184+ const plotDiv = box . querySelector ( '.chart' ) ;
95185 Plotly . newPlot ( plotDiv , plotData , layout , config ) ;
186+
187+ switchToChart ( box ) ; // Switch to chart view immediately after generating the plot
96188 } catch ( error ) {
97189 console . error ( 'Error:' , error ) ;
98190 alert ( 'Invalid JSON data or JSON path' ) ;
99191 }
100192 }
101193
102- let dragEl ;
103- let dragHandleEl
104- const lastPosition = { } ;
194+ function beautifyJson ( box ) {
195+ const jsonInput = box . querySelector ( '.json-input' ) ;
196+ try {
197+ const jsonData = JSON . parse ( jsonInput . value ) ;
198+ jsonInput . value = JSON . stringify ( jsonData , null , 4 ) ;
199+ } catch ( error ) {
200+ console . error ( 'Error:' , error ) ;
201+ alert ( 'Invalid JSON data' ) ;
202+ }
203+ }
105204
106- setupResizable ( ) ;
107- setupDraggable ( ) ;
205+ function setupDraggable ( box ) {
206+ const dragHandleEl = box . querySelector ( '[data-drag-handle]' ) ;
207+ let dragEl ;
208+ let lastPosition = { } ;
108209
109- function setupDraggable ( ) {
110- dragHandleEl = document . querySelector ( '[data-drag-handle]' ) ;
111210 dragHandleEl . addEventListener ( 'mousedown' , dragStart ) ;
112211 dragHandleEl . addEventListener ( 'mouseup' , dragEnd ) ;
113212 dragHandleEl . addEventListener ( 'mouseout' , dragEnd ) ;
114- }
115213
116- function setupResizable ( ) {
117- const resizeEl = document . querySelector ( '[data-resizable]' ) ;
118- resizeEl . style . setProperty ( 'resize ' , 'both ' ) ;
119- resizeEl . style . setProperty ( 'overflow' , 'hidden' ) ;
120- new ResizeObserver ( ( ) => {
121- updatePlotSize ( ) ;
122- } ) . observe ( resizeEl ) ;
123- }
214+ function dragStart ( event ) {
215+ dragEl = box ;
216+ dragEl . style . setProperty ( 'position ' , 'absolute ' ) ;
217+ lastPosition . left = event . clientX ;
218+ lastPosition . top = event . clientY ;
219+ dragHandleEl . classList . add ( 'dragging' ) ;
220+ dragHandleEl . addEventListener ( 'mousemove' , dragMove ) ;
221+ }
124222
125- function dragStart ( event ) {
126- dragEl = getDraggableAncestor ( event . target ) ;
127- dragEl . style . setProperty ( 'position' , 'absolute' ) ;
128- lastPosition . left = event . target . clientX ;
129- lastPosition . top = event . target . clientY ;
130- dragHandleEl . classList . add ( 'dragging' ) ;
131- dragHandleEl . addEventListener ( 'mousemove' , dragMove ) ;
132- }
223+ function dragMove ( event ) {
224+ const dragElRect = dragEl . getBoundingClientRect ( ) ;
225+ const newLeft = dragElRect . left + event . clientX - lastPosition . left ;
226+ const newTop = dragElRect . top + event . clientY - lastPosition . top ;
227+ dragEl . style . setProperty ( 'left' , `${ newLeft } px` ) ;
228+ dragEl . style . setProperty ( 'top' , `${ newTop } px` ) ;
229+ lastPosition . left = event . clientX ;
230+ lastPosition . top = event . clientY ;
231+ window . getSelection ( ) . removeAllRanges ( ) ;
232+ updatePlotSize ( box ) ;
233+ }
133234
134- function dragMove ( event ) {
135- const dragElRect = dragEl . getBoundingClientRect ( ) ;
136- const newLeft = dragElRect . left + event . clientX - lastPosition . left ;
137- const newTop = dragElRect . top + event . clientY - lastPosition . top ;
138- dragEl . style . setProperty ( 'left' , `${ newLeft } px` ) ;
139- dragEl . style . setProperty ( 'top' , `${ newTop } px` ) ;
140- lastPosition . left = event . clientX ;
141- lastPosition . top = event . clientY ;
142- window . getSelection ( ) . removeAllRanges ( ) ;
143- updatePlotSize ( ) ;
235+ function dragEnd ( ) {
236+ dragHandleEl . classList . remove ( 'dragging' ) ;
237+ dragHandleEl . removeEventListener ( 'mousemove' , dragMove ) ;
238+ dragEl = null ;
239+ }
144240 }
145241
146- function updatePlotSize ( ) {
147- Plotly . Plots . resize ( plotDiv ) ;
242+ function setupResizable ( box ) {
243+ box . style . setProperty ( 'resize' , 'both' ) ;
244+ box . style . setProperty ( 'overflow' , 'hidden' ) ;
245+
246+ new ResizeObserver ( ( ) => {
247+ updatePlotSize ( box ) ;
248+ } ) . observe ( box ) ;
148249 }
149250
150- function getDraggableAncestor ( element ) {
151- if ( element . getAttribute ( 'data-draggable' ) ) return element ;
152- return getDraggableAncestor ( element . parentElement ) ;
251+ function setupZIndex ( box ) {
252+ box . addEventListener ( 'mousedown' , ( ) => {
253+ document . querySelectorAll ( '.box' ) . forEach ( b => b . style . zIndex = 0 ) ;
254+ box . style . zIndex = 10 ;
255+ } ) ;
153256 }
154257
155- function dragEnd ( ) {
156- dragHandleEl . classList . remove ( 'dragging' ) ;
157- dragHandleEl . removeEventListener ( 'mousemove' , dragMove ) ;
158- dragEl = null ;
258+ function updatePlotSize ( box ) {
259+ const plotDiv = box . querySelector ( '.chart' ) ;
260+ if ( plotDiv ) {
261+ Plotly . Plots . resize ( plotDiv ) ;
262+ }
159263 }
264+
265+ // Add initial box on load
266+ addNewBox ( ) ;
160267</ script >
161268</ body >
162269</ html >
0 commit comments