new chart resize functionality; removed dependency on CSS-Element-Queries; added option to enable or disable smooth lines plotter
Costa Tsaousis (ktsaou) committed
Dec 23, 2015 at 03:04 UTC
14f580429703aae4d2433dbf0717f71c1fe1026a
3 files changed
+150
-81
web/dashboard.css
+17
-30
@@ -19,37 +19,24 @@ html {
19
/* width and height is given per chart with data-width and data-height */
20
}
21
22
-.netdata-container-resizable {
23
- display: -webkit-flex; /* Safari */
24
- -webkit-flex-wrap: wrap; /* Safari 6.1+ */
25
- display: inline-block;
26
- flex-wrap: wrap;
22
+.netdata-legend-resize-handler {
23
+ display: block;
24
+ position: absolute;
25
+ bottom: 0px;
26
+ right: 0px;
27
+ height: 15px;
28
+ width: 30px;
29
+ background-color: White;
30
+ font-size: 12px;
31
+ vertical-align: middle;
32
+ line-height: 15px;
33
+ cursor: ns-resize;
34
+ color: #DDDDDD;
35
+ text-align: center;
36
overflow: hidden;
28
-
29
- /* enable CSS3 resizing */
30
- resize: vertical;
31
-
32
- /* required for child elements to have absolute position */
33
- position: relative;
34
-
35
- /* width and height is given per chart with data-width and data-height */
36
-}
37
-
38
-.netdata-container-resizable::after {
39
- /* pointer-events: none; */
40
- font-family: FontAwesome;
41
- color: #999999;
42
- content: "\f078";
43
- font-size: 12px;
44
- position: absolute;
45
- height: 15px;
46
- width: 18px;
47
- text-align: center;
48
- bottom: 0px;
49
- right: -2px;
50
- z-index: 2;
51
- cursor: ns-resize;
52
- background-color: #ffffff;
37
+ z-index: 11;
38
+ padding: 0px;
39
+ margin: 0px;
40
}
41
42
.netdata-message {
web/dashboard.js
+124
-50
@@ -203,7 +203,11 @@
203
204
stop_updates_when_focus_is_lost: true,
205
206
- color_fill_opacity: {
206
+ double_click_speed: 500,
207
+
208
+ smooth_plot: true, // enable smooth plot, where possible
209
+
210
+ color_fill_opacity: {
211
line: 1.0,
212
area: 0.2,
213
stacked: 0.8
@@ -691,6 +695,85 @@
695
this.init();
696
}
697
698
+ // ----------------------------------------------------------------------------------------------------------------
699
+ // Chart Resize
700
+
701
+ chartState.prototype.resizeHandler = function(e) {
702
+ e.preventDefault();
703
+
704
+ if(typeof this.event_resize === 'undefined'
705
+ || this.event_resize.chart_original_w === 'undefined'
706
+ || this.event_resize.chart_original_h === 'undefined')
707
+ this.event_resize = {
708
+ chart_original_w: this.element.clientWidth,
709
+ chart_original_h: this.element.clientHeight,
710
+ last: 0
711
+ };
712
+
713
+ this.event_resize.mouse_start_x = e.clientX;
714
+ this.event_resize.mouse_start_y = e.clientY;
715
+ this.event_resize.chart_start_w = this.element.clientWidth;
716
+ this.event_resize.chart_start_h = this.element.clientHeight;
717
+ this.event_resize.chart_last_w = this.element.clientWidth;
718
+ this.event_resize.chart_last_h = this.element.clientHeight;
719
+
720
+ var resize_height_and_update_chart = function(state, h) {
721
+ state.element.style.height = h.toString() + 'px';
722
+
723
+ NETDATA.options.last_page_scroll = new Date().getTime();
724
+
725
+ if(typeof state.library.resize === 'function')
726
+ state.library.resize(state);
727
+
728
+ if(state.element_legend_childs.nano !== null && state.element_legend_childs.nano_options !== null)
729
+ $(state.element_legend_childs.nano).nanoScroller();
730
+ };
731
+
732
+ var now = new Date().getTime();
733
+ if(now - this.event_resize.last <= NETDATA.options.current.double_click_speed) {
734
+ // double click event
735
+
736
+ var optimal = this.event_resize.chart_last_h
737
+ + this.element_legend_childs.content.scrollHeight
738
+ - this.element_legend_childs.content.clientHeight;
739
+
740
+ if(this.event_resize.chart_last_h != optimal)
741
+ resize_height_and_update_chart(this, optimal);
742
+
743
+ else if(this.event_resize.chart_last_h != this.event_resize.chart_original_h)
744
+ resize_height_and_update_chart(this, this.event_resize.chart_original_h);
745
+ }
746
+ else {
747
+ this.event_resize.last = now;
748
+
749
+ var self = this;
750
+
751
+ document.onmousemove =
752
+ this.element_legend_childs.resize_handler.onmousemove =
753
+ this.element_legend_childs.resize_handler.onmouseout =
754
+ function(e) {
755
+ var newH = self.event_resize.chart_start_h + e.clientY - self.event_resize.mouse_start_y;
756
+
757
+ if(newH >= 70 && newH !== self.event_resize.chart_last_h) {
758
+ resize_height_and_update_chart(self, newH);
759
+ self.event_resize.chart_last_h = newH;
760
+ }
761
+ };
762
+
763
+ document.onmouseup =
764
+ this.element_legend_childs.resize_handler.onmouseup =
765
+ function(e) {
766
+ document.onmouseup =
767
+ document.onmousemove =
768
+ self.element_legend_childs.resize_handler.onmousemove =
769
+ self.element_legend_childs.resize_handler.onmouseout =
770
+ self.element_legend_childs.resize_handler.onmouseup =
771
+ null;
772
+ };
773
+ }
774
+ }
775
+
776
+
777
// ----------------------------------------------------------------------------------------------------------------
778
// global selection sync
779
@@ -1275,6 +1358,8 @@
1358
1359
if(this.hasLegend()) {
1360
this.element_legend_childs = {
1361
+ content: content,
1362
+ resize_handler: document.createElement('div'),
1363
title_date: document.createElement('span'),
1364
title_time: document.createElement('span'),
1365
title_units: document.createElement('span'),
@@ -1294,6 +1379,14 @@
1379
1380
this.element_legend.innerHTML = '';
1381
1382
+ this.element_legend_childs.resize_handler.className += " netdata-legend-resize-handler";
1383
+ this.element_legend_childs.resize_handler.innerHTML = '<i class="fa fa-chevron-up"></i><i class="fa fa-chevron-down"></i>';
1384
+ this.element.appendChild(this.element_legend_childs.resize_handler);
1385
+ var self2 = this;
1386
+ this.element_legend_childs.resize_handler.onmousedown = function(e) {
1387
+ self2.resizeHandler(e);
1388
+ };
1389
+
1390
this.element_legend_childs.title_date.className += " netdata-legend-title-date";
1391
this.element_legend.appendChild(this.element_legend_childs.title_date);
1392
@@ -1317,6 +1410,8 @@
1410
}
1411
else {
1412
this.element_legend_childs = {
1413
+ content: content,
1414
+ resize_handler: null,
1415
title_date: null,
1416
title_time: null,
1417
title_units: null,
@@ -1382,26 +1477,9 @@
1477
1478
if(this.hasLegend() === false)
1479
this.element_legend.style.display = 'none';
1385
- else {
1480
+ else
1481
this.element.appendChild(this.element_legend);
1482
1388
- if(typeof this.___addedContainerResizable___ === 'undefined') {
1389
- this.element.className += " netdata-container-resizable";
1390
- this.___addedContainerResizable___ = true;
1391
-
1392
- var state = this;
1393
- this.resize_sensor = ResizeSensor(this.element, function() {
1394
- NETDATA.options.last_updated = new Date().getTime();
1395
-
1396
- if(typeof state.library.resize === 'function')
1397
- state.library.resize(state);
1398
-
1399
- if(state.element_legend_childs.nano !== null && state.element_legend_childs.nano_options !== null)
1400
- $(state.element_legend_childs.nano).nanoScroller();
1401
- });
1402
- }
1403
- }
1404
-
1483
this.element_legend_childs.series = null;
1484
this.legendUpdateDOM();
1485
@@ -2408,8 +2486,6 @@
2486
}
2487
2488
NETDATA.parseDom = function(callback) {
2411
- ElementQueries.update();
2412
-
2489
NETDATA.options.last_page_scroll = new Date().getTime();
2490
NETDATA.options.updated_dom = false;
2491
@@ -2722,7 +2798,7 @@
2798
NETDATA.error(100, NETDATA.dygraph_js);
2799
})
2800
.always(function() {
2725
- if(NETDATA.chartLibraries.dygraph.enabled === true)
2801
+ if(NETDATA.chartLibraries.dygraph.enabled === true && NETDATA.options.current.smooth_plot === true)
2802
NETDATA.dygraphSmoothInitialize(callback);
2803
else if(typeof callback === "function")
2804
callback();
@@ -2749,31 +2825,34 @@
2825
if(state.tm.last_unhidden > state.dygraph_last_rendered)
2826
dygraph.resize();
2827
2752
- if(state.current.name === 'pan') {
2753
- if(NETDATA.options.debug.dygraph === true || state.debug === true)
2754
- state.log('dygraphChartUpdate() loose update');
2755
-
2756
- dygraph.updateOptions({
2828
+ var options = {
2829
file: data.result.data,
2830
colors: state.chartColors(),
2831
labels: data.result.labels,
2832
labelsDivWidth: state.chartWidth() - 70
2761
- });
2833
+ }
2834
+
2835
+ if(state.current.name === 'pan') {
2836
+ if(NETDATA.options.debug.dygraph === true || state.debug === true)
2837
+ state.log('dygraphChartUpdate() loose update');
2838
}
2839
else {
2840
if(NETDATA.options.debug.dygraph === true || state.debug === true)
2841
state.log('dygraphChartUpdate() strict update');
2842
+
2843
+ options.dateWindow = null;
2844
+ options.valueRange = null;
2845
+ }
2846
2767
- dygraph.updateOptions({
2768
- file: data.result.data,
2769
- colors: state.chartColors(),
2770
- labels: data.result.labels,
2771
- labelsDivWidth: state.chartWidth() - 70,
2772
- dateWindow: null,
2773
- valueRange: null
2774
- });
2847
+ if(state.dygraph_smooth_eligible === true) {
2848
+ if((NETDATA.options.current.smooth_plot === true && state.dygraph_options.plotter !== smoothPlotter)
2849
+ || (NETDATA.options.current.smooth_plot === false && state.dygraph_options.plotter === smoothPlotter)) {
2850
+ NETDATA.dygraphChartCreate(state, data);
2851
+ return;
2852
+ }
2853
}
2854
2855
+ dygraph.updateOptions(options);
2856
state.dygraph_last_rendered = new Date().getTime();
2857
};
2858
@@ -2796,7 +2875,6 @@
2875
var strokeWidth = (chart_type === 'stacked')?0.0:((smooth)?1.5:1.0)
2876
var highlightCircleSize = (NETDATA.chartLibraries.dygraph.isSparkline(state))?3:4;
2877
2799
-
2878
state.dygraph_options = {
2879
colors: self.data('dygraph-colors') || state.chartColors(),
2880
@@ -3209,12 +3287,12 @@
3287
state.globalSelectionSync(t);
3288
}
3289
3212
- // if it was double tap within 250ms, reset the charts
3290
+ // if it was double tap within double click time, reset the charts
3291
var now = new Date().getTime();
3292
if(typeof state.dygraph_last_touch_end !== 'undefined') {
3293
if(state.dygraph_last_touch_move === 0) {
3294
var dt = now - state.dygraph_last_touch_end;
3217
- if(dt <= 250) {
3295
+ if(dt <= NETDATA.options.current.double_click_speed) {
3296
state.globalSelectionSyncStop();
3297
NETDATA.globalPanAndZoom.clearMaster();
3298
state.resetChart();
@@ -3241,7 +3319,13 @@
3319
state.dygraph_options.rightGap = 0;
3320
}
3321
3244
- if(smooth === true) state.dygraph_options.plotter = smoothPlotter;
3322
+ if(smooth === true) {
3323
+ state.dygraph_smooth_eligible = true;
3324
+
3325
+ if(NETDATA.options.current.smooth_plot === true)
3326
+ state.dygraph_options.plotter = smoothPlotter;
3327
+ }
3328
+ else state.dygraph_smooth_eligible = false;
3329
3330
state.dygraph_instance = new Dygraph(state.element_chart,
3331
data.result.data, state.dygraph_options);
@@ -3725,14 +3809,6 @@
3809
url: NETDATA.serverDefault + 'lib/jquery.nanoscroller.min.js',
3810
isAlreadyLoaded: function() { return false; }
3811
},
3728
- {
3729
- url: NETDATA.serverDefault + 'lib/ResizeSensor.js',
3730
- isAlreadyLoaded: function() { return false; }
3731
- },
3732
- {
3733
- url: NETDATA.serverDefault + 'lib/ElementQueries.js',
3734
- isAlreadyLoaded: function() { return false; }
3735
- },
3812
{
3813
url: NETDATA.serverDefault + 'lib/bootstrap-toggle.min.js',
3814
isAlreadyLoaded: function() { return false; }
@@ -3815,8 +3891,6 @@
3891
3892
NETDATA._loadjQuery(function() {
3893
NETDATA.loadRequiredJs(0, function() {
3818
- ElementQueries.init();
3819
-
3894
// keep a copy of the default settings
3895
NETDATA.options.defaults = $.extend({}, NETDATA.options.current);
3896
web/index.html
+9
-1
@@ -253,7 +253,7 @@
253
<!-- <script> netdataServer = "http://box:19999"; </script> -->
254
255
<!-- load the dashboard manager - it will do the rest -->
256
- <script type="text/javascript" src="dashboard.js?v4"></script>
256
+ <script type="text/javascript" src="dashboard.js?v5"></script>
257
</head>
258
259
<body data-spy="scroll" data-target="#sidebar">
@@ -479,6 +479,12 @@
479
<small>When enabled, pan and zoom operations on a chart will be replicated to all charts (even the ones that are not currently visible - of course only when they will become visible). When disabled, pan and zoom operations will not be propagated to other charts.</small>
480
</td>
481
</tr>
482
+ <tr class="option-row">
483
+ <td class="option-control"><input id="smooth_plot" type="checkbox" checked data-toggle="toggle" data-on="Smooth" data-off="Rough" data-width="110px"></td>
484
+ <td class="option-info"><strong>Enable Bézier lines on charts?</strong><br/>
485
+ <small>When set to <b>Smooth</b> the charts libraries that support it, will plot smooth curves instead of simple straight lines to connect the points.</small>
486
+ </td>
487
+ </tr>
488
</table>
489
</div>
490
</form>
@@ -1015,6 +1021,7 @@ function prepareScreen(data) {
1021
sync_option('sync_selection');
1022
sync_option('sync_pan_and_zoom');
1023
sync_option('stop_updates_when_focus_is_lost');
1024
+ sync_option('smooth_plot');
1025
1026
if(NETDATA.getOption('parallel_refresher') === false) {
1027
$('#concurrent_refreshes_row').hide();
@@ -1033,6 +1040,7 @@ function prepareScreen(data) {
1040
$('#sync_selection').change(function() { NETDATA.setOption('sync_selection', $(this).prop('checked')); });
1041
$('#sync_pan_and_zoom').change(function() { NETDATA.setOption('sync_pan_and_zoom', $(this).prop('checked')); });
1042
$('#stop_updates_when_focus_is_lost').change(function() { NETDATA.setOption('stop_updates_when_focus_is_lost', $(this).prop('checked')); });
1043
+ $('#smooth_plot').change(function() { NETDATA.setOption('smooth_plot', $(this).prop('checked')); });
1044
1045
if(document.location.hostname === demo_hostname)
1046
setTimeout(function() {