@cryptotaxi247 / netdata-1 / commits / 5496d67ac

dimensions can now be turned on and off using the legend

Costa Tsaousis (ktsaou) committed Dec 25, 2015 at 01:38 UTC 5496d67ace272b7e640388b0e9cec5818f145f4a
2 files changed +218 -8
web/dashboard.css
+4
@@ -225,6 +225,10 @@ html {
225 padding: 0px;
226 padding-left: 15px;
227 }
228 +.netdata-legend-name.not-selected {
229 + font-weight: normal;
230 + opacity: 0.3;
231 +}
232
233 .netdata-chart {
234 position: absolute; /* within .netdata-container */
web/dashboard.js
+214 -8
@@ -542,6 +542,205 @@
542 }
543 }
544
545 + // ----------------------------------------------------------------------------------------------------------------
546 + // dimensions selection
547 +
548 + // FIXME
549 +
550 + dimensionStatus = function(parent, label, name_div, value_div, color) {
551 + this.enabled = false;
552 + this.parent = parent;
553 + this.label = label;
554 + this.name_div = null;
555 + this.value_div = null;
556 + this.color = '#000';
557 +
558 + if(parent.selected === parent.unselected)
559 + this.selected = true;
560 + else
561 + this.selected = false;
562 +
563 + this.setOptions(name_div, value_div, color);
564 + }
565 +
566 + dimensionStatus.prototype.invalidate = function() {
567 + this.name_div = null;
568 + this.value_div = null;
569 + this.enabled = false;
570 + }
571 +
572 + dimensionStatus.prototype.setOptions = function(name_div, value_div, color) {
573 + this.color = color;
574 +
575 + if(this.name_div != name_div) {
576 + this.name_div = name_div;
577 + this.name_div.title = this.label;
578 + this.name_div.style.color = this.color;
579 + if(this.selected === false)
580 + this.name_div.className = 'netdata-legend-name not-selected';
581 + else
582 + this.name_div.className = 'netdata-legend-name selected';
583 + }
584 +
585 + if(this.value_div != value_div) {
586 + this.value_div = value_div;
587 + this.value_div.title = this.label;
588 + this.value_div.style.color = this.color;
589 + if(this.selected === false)
590 + this.value_div.className = 'netdata-legend-value not-selected';
591 + else
592 + this.value_div.className = 'netdata-legend-value selected';
593 + }
594 +
595 + this.enabled = true;
596 + this.setHandler();
597 + }
598 +
599 + dimensionStatus.prototype.setHandler = function() {
600 + if(this.enabled === false) return;
601 +
602 + var ds = this;
603 +
604 + // this.name_div.onmousedown = this.value_div.onmousedown = function(e) {
605 + this.name_div.onclick = this.value_div.onclick = function(e) {
606 + e.preventDefault();
607 + if(ds.isSelected()) {
608 + // this is selected
609 + if(e.shiftKey === true || e.ctrlKey === true) {
610 + // control or shift key is pressed -> unselect this (except is none will remain selected, in which case select all)
611 + ds.unselect();
612 +
613 + if(ds.parent.countSelected() === 0)
614 + ds.parent.selectAll();
615 + }
616 + else {
617 + // no key is pressed -> select only this (except if it is the only selected already, in which case select all)
618 + if(ds.parent.countSelected() === 1) {
619 + ds.parent.selectAll();
620 + }
621 + else {
622 + ds.parent.selectNone();
623 + ds.select();
624 + }
625 + }
626 + }
627 + else {
628 + // this is not selected
629 + if(e.shiftKey === true || e.ctrlKey === true) {
630 + // control or shift key is pressed -> select this too
631 + ds.select();
632 + }
633 + else {
634 + // no key is pressed -> select only this
635 + ds.parent.selectNone();
636 + ds.select();
637 + }
638 + }
639 +
640 + ds.parent.state.redrawChart();
641 + }
642 + }
643 +
644 + dimensionStatus.prototype.select = function() {
645 + if(this.enabled === false) return;
646 +
647 + this.name_div.className = 'netdata-legend-name selected';
648 + this.value_div.className = 'netdata-legend-value selected';
649 + this.selected = true;
650 + }
651 +
652 + dimensionStatus.prototype.unselect = function() {
653 + if(this.enabled === false) return;
654 +
655 + this.name_div.className = 'netdata-legend-name not-selected';
656 + this.value_div.className = 'netdata-legend-value hidden';
657 + this.selected = false;
658 + }
659 +
660 + dimensionStatus.prototype.isSelected = function() {
661 + return(this.enabled === true && this.selected === true);
662 + }
663 +
664 + // ----------------------------------------------------------------------------------------------------------------
665 +
666 + dimensionsVisibility = function(state) {
667 + this.state = state;
668 + this.len = 0;
669 + this.dimensions = {};
670 + this.selected_count = 0;
671 + this.unselected_count = 0;
672 + }
673 +
674 + dimensionsVisibility.prototype.dimensionAdd = function(label, name_div, value_div, color) {
675 + if(typeof this.dimensions[label] === 'undefined') {
676 + this.len++;
677 + this.dimensions[label] = new dimensionStatus(this, label, name_div, value_div, color);
678 + }
679 + else
680 + this.dimensions[label].setOptions(name_div, value_div, color);
681 +
682 + return this.dimensions[label];
683 + }
684 +
685 + dimensionsVisibility.prototype.dimensionGet = function(label) {
686 + return this.dimensions[label];
687 + }
688 +
689 + dimensionsVisibility.prototype.invalidateAll = function() {
690 + for(var d in this.dimensions)
691 + this.dimensions[d].invalidate();
692 + }
693 +
694 + dimensionsVisibility.prototype.selectAll = function() {
695 + for(var d in this.dimensions)
696 + this.dimensions[d].select();
697 + }
698 +
699 + dimensionsVisibility.prototype.countSelected = function() {
700 + var i = 0;
701 + for(var d in this.dimensions)
702 + if(this.dimensions[d].isSelected()) i++;
703 +
704 + return i;
705 + }
706 +
707 + dimensionsVisibility.prototype.selectNone = function() {
708 + for(var d in this.dimensions)
709 + this.dimensions[d].unselect();
710 + }
711 +
712 + dimensionsVisibility.prototype.selected2BooleanArray = function(array) {
713 + var ret = new Array();
714 + this.selected_count = 0;
715 + this.unselected_count = 0;
716 +
717 + for(var i = 0, len = array.length; i < len ; i++) {
718 + var ds = this.dimensions[array[i]];
719 + if(typeof ds === 'undefined') {
720 + // console.log(array[i] + ' is not found');
721 + ret.push(false);
722 + continue;
723 + }
724 +
725 + if(ds.isSelected()) {
726 + ret.push(true);
727 + this.selected_count++;
728 + }
729 + else {
730 + ret.push(false);
731 + this.unselected_count++;
732 + }
733 + }
734 +
735 + if(this.selected_count === 0 && this.unselected_count !== 0) {
736 + this.selectAll();
737 + return this.selected2BooleanArray(array);
738 + }
739 +
740 + return ret;
741 + }
742 +
743 +
744 // ----------------------------------------------------------------------------------------------------------------
745 // Our state object, where all per-chart values are stored
746
@@ -640,6 +839,8 @@
839 netdata_first: 0, // milliseconds - the first timestamp in netdata
840 netdata_last: 0, // milliseconds - the last timestamp in netdata
841
842 + dimensions_visibility: new dimensionsVisibility(this),
843 +
844 current: null, // auto, pan, zoom
845 // this is a pointer to one of the sub-classes below
846
@@ -1326,6 +1527,9 @@
1527 if(this.debug === true)
1528 this.log('updating Legend DOM');
1529
1530 + // mark all dimensions as invalid
1531 + this.dimensions_visibility.invalidateAll();
1532 +
1533 var self = $(this.element);
1534 var genLabel = function(state, parent, name, count) {
1535 var color = state._chartDimensionColor(name);
@@ -1347,10 +1551,8 @@
1551
1552 var label = state.element_legend_childs.series[name];
1553
1350 - label.name.className += ' netdata-legend-name';
1351 - label.value.className += ' netdata-legend-value';
1352 - label.name.title = name;
1353 - label.value.title = name;
1554 + // create the dimension visibility tracking for this label
1555 + var ds = state.dimensions_visibility.dimensionAdd(name, label.name, label.value, color);
1556
1557 var rgb = NETDATA.colorHex2Rgb(color);
1558 label.name.innerHTML = '<table class="netdata-legend-name-table-'
@@ -1362,9 +1564,6 @@
1564 var text = document.createTextNode(' ' + name);
1565 label.name.appendChild(text);
1566
1365 - label.name.style.color = color;
1366 - label.value.style.color = color;
1367 -
1567 if(count > 0)
1568 parent.appendChild(document.createElement('br'));
1569
@@ -1622,6 +1821,11 @@
1821 this.log('chartURL(): ' + this.data_url + ' WxH:' + this.chartWidth() + 'x' + this.chartHeight() + ' points: ' + this.data_points + ' library: ' + this.library_name);
1822 }
1823
1824 + chartState.prototype.redrawChart = function() {
1825 + if(this.data !== null)
1826 + this.updateChartWithData(this.data);
1827 + }
1828 +
1829 chartState.prototype.updateChartWithData = function(data) {
1830 if(this.debug === true)
1831 this.log('got data from netdata server');
@@ -2858,7 +3062,8 @@
3062 file: data.result.data,
3063 colors: state.chartColors(),
3064 labels: data.result.labels,
2861 - labelsDivWidth: state.chartWidth() - 70
3065 + labelsDivWidth: state.chartWidth() - 70,
3066 + visibility: state.dimensions_visibility.selected2BooleanArray(state.data.dimension_names)
3067 }
3068
3069 if(state.current.name === 'pan') {
@@ -2981,6 +3186,7 @@
3186 highlightSeriesBackgroundAlpha: self.data('dygraph-highlightseriesbackgroundalpha') || null, // TOO SLOW: (chart_type === 'stacked')?0.7:0.5,
3187
3188 pointClickCallback: self.data('dygraph-pointclickcallback') || undefined,
3189 + visibility: state.dimensions_visibility.selected2BooleanArray(state.data.dimension_names),
3190 axes: {
3191 x: {
3192 pixelsPerLabel: 50,