Advertisement
Guest User

SerialChartCustomized

a guest
Jul 11th, 2018
121
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /* Modified from https://github.com/infiniteautomation/ma-dashboards/blob/3.3.x/UI/web/ngMango/directives/serialChart.js */
  2.  
  3. userModule.directive('myCustomMangoChart',
  4. function(){
  5.    
  6.     var MAX_SERIES = 10;
  7.    
  8.    
  9.     var scope = {
  10.         options: '<?',
  11.         timeFormat: '@',
  12.         timezone: '@',
  13.         stackType: '@',
  14.         values: '<?',
  15.         points: '<?',
  16.         graphOptions: '<?',
  17.         defaultType: '@',
  18.         defaultColor: '@',
  19.         defaultAxis: '@',
  20.         defaultBalloonText: '@',
  21.         defaultGraphOptions: '<?',
  22.         'export': '<?',
  23.         oneBalloon: '<?',
  24.         legend: '<?',
  25.         customBullet: '@',
  26.         bullet: '@',
  27.         annotateMode: '<?',
  28.         lineThickness: '@',
  29.         onChartInit: '&?',
  30.         graphItemClicked: '&?',
  31.         trendLines: '<?',
  32.         guides: '<?',
  33.         cursorSyncId: '@?',
  34.         end:'<?',
  35.         hours:'<?',
  36.         selected:'=?',
  37.         pointTitle: '&?'
  38.     };
  39.  
  40.     for (var j = 1; j <= MAX_SERIES; j++) {
  41.         scope['series' + j + 'Values'] = '<?';
  42.         scope['series' + j + 'Type'] = '@';
  43.         scope['series' + j + 'Title'] = '@';
  44.         scope['series' + j + 'Color'] = '@';
  45.         scope['series' + j + 'Axis'] = '@';
  46.         scope['series' + j + 'BalloonText'] = '@';
  47.         scope['series' + j + 'Point'] = '<?';
  48.         scope['series' + j + 'GraphOptions'] = '<?';
  49.     }
  50.    
  51.     const cursorSyncCharts = {};
  52.    
  53.     const addCursorSyncChart = (cursorSyncId, chart) => {
  54.         if (!cursorSyncCharts.hasOwnProperty(cursorSyncId)) {
  55.             cursorSyncCharts[cursorSyncId] = [];
  56.         }
  57.         if (cursorSyncCharts[cursorSyncId].includes(chart)) return;
  58.         cursorSyncCharts[cursorSyncId].push(chart);
  59.     };
  60.    
  61.     const removeCursorSyncChart = (cursorSyncId, chart) => {
  62.         const chartsArray = cursorSyncCharts[cursorSyncId];
  63.         if (!chartsArray) return;
  64.         const index = chartsArray.indexOf(chart);
  65.         if (index >= 0) {
  66.             chartsArray.splice(index, 1);
  67.         }
  68.         if (!chartsArray.length) {
  69.             delete cursorSyncCharts[cursorSyncId];
  70.         }
  71.     };
  72.    
  73.     const chartZoomed = (cursorSyncId, event) => {
  74.         const chartsArray = cursorSyncCharts[cursorSyncId];
  75.         if (!chartsArray) return;
  76.         chartsArray.forEach(chart => {
  77.             if (chart.ignoreZoom) {
  78.                 chart.ignoreZoom = false;
  79.             }
  80.             if (chart !== event.chart) {
  81.                 chart.ignoreZoom = true;
  82.                 try {
  83.                     chart.zoomToDates(event.startDate, event.endDate);
  84.                 } catch (e) {} // throws error on first run
  85.             }
  86.         });
  87.     };
  88.    
  89.     const cursorChanged = (cursorSyncId, event) => {
  90.         const chartsArray = cursorSyncCharts[cursorSyncId];
  91.         if (!chartsArray) return;
  92.         chartsArray.forEach(chart => {
  93.             if (chart !== event.chart) {
  94.                 chart.chartCursor.syncWithCursor(event.chart.chartCursor);
  95.             }
  96.         });
  97.     };
  98.    
  99.     const cursorHidden = (cursorSyncId, event) => {
  100.         const chartsArray = cursorSyncCharts[cursorSyncId];
  101.         if (!chartsArray) return;
  102.         chartsArray.forEach(chart => {
  103.             if (chart.chartCursor.hideCursor) {
  104.                 chart.chartCursor.forceShow = false;
  105.                 chart.chartCursor.hideCursor(false);
  106.             }
  107.         });
  108.     };
  109.    
  110.     return {
  111.         restrict: 'E',
  112.         scope: scope,
  113.         compile: function() {
  114.             return postLink;
  115.         }
  116.     };
  117.    
  118.     function postLink($scope, $element, attrs) {
  119.         $element.addClass('amchart');
  120.        
  121.         var options = defaultOptions();
  122.  
  123.         if ($scope.timeFormat) {
  124.             options.categoryAxis.parseDates = false;
  125.         }
  126.  
  127.         if ($scope.stackType) {
  128.             options.valueAxes[0].stackType = $scope.stackType;
  129.         }
  130.        
  131.         if ($scope.legend) {
  132.             options.legend = {
  133.                 valueWidth: 100,
  134.                 valueFunction: dataItemToText
  135.             };
  136.         }
  137.        
  138.         if ($scope['export']) {
  139.             options['export'].enabled = true;
  140.         }
  141.        
  142.         if ($scope.oneBalloon) {
  143.             options.chartCursor = {
  144.                 oneBalloonOnly: true
  145.             };
  146.         }
  147.  
  148.         if ($scope.annotateMode) {
  149.             options.chartCursor = {
  150.                 oneBalloonOnly: true,
  151.                 graphBulletSize: 2,
  152.                 zoomable: false,
  153.                 categoryBalloonDateFormat: 'h:mm:ss A - MMM DD, YYYY'
  154.             };
  155.             options.balloon = {
  156.                 fillAlpha: 1
  157.             };
  158.         }
  159.  
  160.         var valueArray = !!attrs.values;
  161.  
  162.         $.extend(true, options, $scope.options);
  163.  
  164.         var chart = AmCharts.makeChart($element[0], angular.copy(options));
  165.        
  166.         if ($scope.onChartInit) {
  167.             $scope.onChartInit({$chart: chart});
  168.         }
  169.        
  170.         if ($scope.cursorSyncId) {
  171.             addCursorSyncChart($scope.cursorSyncId, chart);
  172.             $scope.$on('$destroy', () => removeCursorSyncChart($scope.cursorSyncId, chart));
  173.         }
  174.  
  175.  
  176.         // Added listeners from previous component
  177.  
  178.         chart.addListener("dataUpdated", () => {
  179.             if (angular.isArray(chart.dataProvider) && typeof $scope.end !== "undefined"){
  180.  
  181.                 var e = moment($scope.end);
  182.                 // Default zooming interval is 12 hours if not defined otherway
  183.                 var hourvar;
  184.                
  185.                 if (typeof $scope.hours !== "undefined"){
  186.                     hourvar = $scope.hours;
  187.                 }else{
  188.                     hourvar = 12;
  189.                 }
  190.                
  191.                 var s = moment($scope.end).subtract(hourvar, 'hours');
  192.                 e = e.toDate();
  193.                 s = s.toDate();
  194.                
  195.                 console.log(e);
  196.                 console.log(s);
  197.                 chart.zoomToDates(s, e);
  198.           }
  199.            
  200.         });
  201.        
  202.         chart.addListener('zoomed', event => {
  203.             if ($scope.cursorSyncId) {
  204.                 chartZoomed($scope.cursorSyncId, event);
  205.             }
  206.             if (angular.isArray(chart.dataProvider)){
  207.                 $scope.selected = [];
  208.                 let s = moment(chart.startDate).format('LLL');
  209.                 let e = moment(chart.endDate).format('LLL');
  210.                 $scope.selected.push({
  211.                    start : s,
  212.                    end : e
  213.                     });
  214.    
  215.             }
  216.         });
  217.        
  218.         if (chart.chartCursor) {
  219.             chart.chartCursor.addListener('changed', event => {
  220.                 if ($scope.cursorSyncId) {
  221.                     cursorChanged($scope.cursorSyncId, event);
  222.                 }
  223.             });
  224.    
  225.             chart.chartCursor.addListener('onHideCursor', event => {
  226.                 if ($scope.cursorSyncId) {
  227.                     cursorHidden($scope.cursorSyncId, event);
  228.                 }
  229.             });
  230.         }
  231.  
  232.         chart.addListener('changed', function(event) {
  233.             chart.lastCursorPosition = event.index;
  234.         });
  235.        
  236.         if ($scope.graphItemClicked) {
  237.             chart.addListener('clickGraphItem', function(event) {
  238.                 $scope.graphItemClicked({$chart: chart, $event: event});
  239.             });
  240.         }
  241.  
  242.         $scope.$watchCollection('trendLines', function(newValue, oldValue) {
  243.             if (newValue === oldValue && newValue === undefined) return;
  244.             $scope.options.trendLines = newValue;
  245.         });
  246.  
  247.         $scope.$watch('guides', (newValue, oldValue) => {
  248.             if (newValue === oldValue && newValue === undefined) return;
  249.             if (!chart || !chart.categoryAxis) return;
  250.  
  251.             let guides = newValue;
  252.             if (!Array.isArray(guides)) {
  253.                 guides = [];
  254.             }
  255.             // must copy the guides as amCharts turns modifies the guide objects causing infinite digest errors
  256.             chart.categoryAxis.guides = angular.copy(guides);
  257.             chart.validateNow();
  258.         }, true);
  259.  
  260.         $scope.$watch('options', function(newValue, oldValue) {
  261.             if (!newValue) return;
  262.            
  263.             $.extend(true, chart, newValue);
  264.             checkForAxisColors();
  265.             watchPointsAndGraphs($scope.graphOptions);
  266.         }, true);
  267.  
  268.         $scope.$watchGroup([
  269.             'defaultType',
  270.             'defaultColor',
  271.             'defaultAxis',
  272.             'defaultBalloonText',
  273.             'defaultGraphOptions'
  274.         ], graphOptionsChanged.bind(null, null));
  275.  
  276.         if (valueArray) {
  277.             $scope.$watchCollection('values', watchValues);
  278.             $scope.$watchCollection('points', watchPointsAndGraphs);
  279.             $scope.$watch('graphOptions', watchPointsAndGraphs, true);
  280.         }
  281.        
  282.         for (var i = 1; i <= MAX_SERIES; i++) {
  283.             var seriesAttributes = [
  284.                 'series' + i + 'Type',
  285.                 'series' + i + 'Title',
  286.                 'series' + i + 'Color',
  287.                 'series' + i + 'Axis',
  288.                 'series' + i + 'BalloonText',
  289.                 'series' + i + 'GraphOptions'
  290.             ];
  291.            
  292.             if (!valueArray) {
  293.                 seriesAttributes.push('series' + i + 'Values');
  294.                 seriesAttributes.push('series' + i + 'Point');
  295.             }
  296.            
  297.             var hasSeries = false;
  298.             for (var j = 0; j < seriesAttributes.length; j++) {
  299.                 if (!angular.isUndefined(attrs[seriesAttributes[j]])) {
  300.                     hasSeries = true;
  301.                     break;
  302.                 }
  303.             }
  304.            
  305.             if (hasSeries) {
  306.                 $scope.$watchGroup(seriesAttributes, graphOptionsChanged.bind(null, i));
  307.                 if (!valueArray) {
  308.                     $scope.$watchCollection('series' + i + 'Values', valuesChanged.bind(null, i));
  309.                 }
  310.             }
  311.         }
  312.  
  313.         function watchValues(newValues, oldValues) {
  314.             if (newValues === oldValues && newValues === undefined) return;
  315.            
  316.             chart.dataProvider = newValues;
  317.             checkEqualSpacing();
  318.             chart.validateData();
  319.         }
  320.        
  321.         function checkEqualSpacing() {
  322.             if (options.categoryAxis.equalSpacing) return;
  323.  
  324.             if (chart.dataProvider) {
  325.                 chart.categoryAxis.equalSpacing = !chart.dataProvider.map(function(dataItem, index, array) {
  326.                     if (index === 0) return null;
  327.                     return dataItem.timestamp - array[index - 1].timestamp;
  328.                 }).some(function(diff, index, array) {
  329.                     if (index <= 1) return;
  330.                     return diff !== array[index - 1];
  331.                 });
  332.             } else {
  333.                 chart.categoryAxis.equalSpacing = true;
  334.             }
  335.         }
  336.  
  337.         function watchPointsAndGraphs(newValues, oldValues) {
  338.             if (newValues === oldValues && newValues === undefined) return;
  339.            
  340.             if (!$scope.points && !$scope.graphOptions) {
  341.                 chart.graphs = [];
  342.             }
  343.  
  344.             if (newValues) {
  345.                 var numGraphs = $scope.points && $scope.points.length || 0;
  346.                 var graphOptionsLength = $scope.graphOptions && $scope.graphOptions.length || 0;
  347.                 if (graphOptionsLength > numGraphs) {
  348.                     numGraphs = graphOptionsLength;
  349.                 }
  350.                 while (chart.graphs.length > numGraphs) {
  351.                     chart.graphs.pop();
  352.                 }
  353.                
  354.                 for (var i = 0; i < newValues.length; i++) {
  355.                     var val = newValues[i];
  356.                     if (!val) continue;
  357.                     setupGraph(i + 1);
  358.                 }
  359.             }
  360.  
  361.             sortGraphs();
  362.             chart.validateNow(true);
  363.         }
  364.  
  365.         function findGraph(propName, prop, removeGraph) {
  366.             for (var i = 0; i < chart.graphs.length; i++) {
  367.                 if (chart.graphs[i][propName] === prop) {
  368.                     var graph = chart.graphs[i];
  369.                     if (removeGraph) chart.graphs.splice(i, 1);
  370.                     return graph;
  371.                 }
  372.             }
  373.         }
  374.  
  375.         function graphOptionsChanged(graphNum, values) {
  376.             if (isAllUndefined(values)) return;
  377.  
  378.             if (graphNum === null) {
  379.                 // update all graphs
  380.                 for (var i = 0; i < chart.graphs.length; i++) {
  381.                     setupGraph(chart.graphs[i]);
  382.                 }
  383.             } else {
  384.                 setupGraph(graphNum);
  385.             }
  386.  
  387.             sortGraphs();
  388.             chart.validateNow(true);
  389.         }
  390.  
  391.         function valuesChanged(graphNum, newValues, oldValues) {
  392.             if (newValues === oldValues && newValues === undefined) return;
  393.  
  394.             if (!newValues) {
  395.                 findGraph('graphNum', graphNum, true);
  396.             } else  {
  397.                 setupGraph(graphNum);
  398.                 sortGraphs();
  399.             }
  400.             updateValues();
  401.         }
  402.        
  403.         function getPointForGraph(graphNum) {
  404.             var point = $scope['series' + graphNum + 'Point'];
  405.             if (!point && $scope.points) {
  406.                 point = $scope.points[graphNum - 1];
  407.             }
  408.             return point;
  409.         }
  410.  
  411.         function setupGraph(graphNum, point) {
  412.             var graph;
  413.            
  414.             // first arg can be the graph itself
  415.             if (typeof graphNum === 'object') {
  416.                 graph = graphNum;
  417.                 graphNum = graph.graphNum;
  418.             } else {
  419.                 graph = findGraph('graphNum', graphNum);
  420.             }
  421.             if (!graph) {
  422.                 graph = {};
  423.                 chart.graphs.push(graph);
  424.             }
  425.            
  426.             var hardDefaults = {
  427.                 graphNum: graphNum,
  428.                 id: 'series-' + graphNum,
  429.                 valueField: 'value_' + graphNum,
  430.                 title: 'Series ' + graphNum,
  431.                 type: 'smoothedLine',
  432.                 valueAxis: 'left',
  433.                 clustered: false,
  434.                 balloonFunction: function(dataItem, graph) {
  435.                     var valueForBalloon = dataItemToText(dataItem);
  436.                     if ($scope.annotateMode) {
  437.                         return dataItem.dataContext[graph.xid + 'AnnotationBalloonText'] ?
  438.                                 dataItem.dataContext[graph.xid + 'AnnotationBalloonText'] :
  439.                                 valueForBalloon;
  440.                     } else {
  441.                         return valueForBalloon;
  442.                     }
  443.                 }
  444.             };
  445.  
  446.             var pointDefaults;
  447.             point = point || getPointForGraph(graphNum);
  448.             if (point) {
  449.                 pointDefaults = {
  450.                     xid: point.xid,
  451.                     valueField: 'value_' + point.xid,
  452.                     title: point.deviceName + ' - ' + point.name,
  453.                     lineColor: point.chartColour
  454.                 };
  455.                
  456.                 if ($scope.pointTitle) {
  457.                     pointDefaults.title = $scope.pointTitle({$point: point});
  458.                 }
  459.                
  460.                 if (typeof point.amChartsGraphType === 'function') {
  461.                     pointDefaults.type = point.amChartsGraphType();
  462.                 }
  463.             }
  464.  
  465.             var defaultAttributes = {
  466.                 type: $scope.defaultType,
  467.                 lineColor: $scope.defaultColor,
  468.                 lineThickness: $scope.lineThickness,
  469.                 valueAxis: $scope.defaultAxis,
  470.                 bullet: $scope.bullet,
  471.                 customBullet: $scope.customBullet
  472.             };
  473.            
  474.             var attributeOptions = {
  475.                 title: $scope['series' + graphNum + 'Title'],
  476.                 type: $scope['series' + graphNum + 'Type'],
  477.                 lineColor: $scope['series' + graphNum + 'Color'],
  478.                 valueAxis: $scope['series' + graphNum + 'Axis'],
  479.                 balloonText: $scope['series' + graphNum + 'BalloonText']
  480.             };
  481.            
  482.             var graphOptions = $scope['series' + graphNum + 'GraphOptions'] ||
  483.                 ($scope.graphOptions && $scope.graphOptions[graphNum - 1]);
  484.  
  485.             var annotateOptions = {};
  486.  
  487.             if ($scope.annotateMode) {
  488.                 annotateOptions = {
  489.                     labelText: '[[' + graph.xid + 'AnnotationText]]',
  490.                     labelRotation: 0,
  491.                     labelPosition: 'right',
  492.                     labelOffset: 5,
  493.                     labelColorField: graph.xid + 'AnnotationTextColor',
  494.                     bulletSize: 10,
  495.                     bulletSizeField: graph.xid + 'AnnotationBulletSize',
  496.                     bulletHitAreaSize: 14,
  497.                     bulletAlpha: 1,
  498.                     bulletColor: 'rgba(0, 0, 0, 0)',
  499.                     bullet: 'circle',
  500.                     bulletField: graph.xid + 'AnnotationBullet'
  501.                 };
  502.             }
  503.  
  504.             var opts = $.extend(true, {}, hardDefaults, pointDefaults, $scope.defaultGraphOptions,
  505.                     defaultAttributes, attributeOptions, graphOptions, annotateOptions);
  506.  
  507.             var graphAxis;
  508.             chart.valueAxes.some(function(axis) {
  509.                 if (axis.id === opts.valueAxis) {
  510.                     graphAxis = axis;
  511.                     return true;
  512.                 }
  513.             });
  514.            
  515.             if (opts.balloonText)
  516.                 delete opts.balloonFunction;
  517.             if (angular.isUndefined(opts.fillAlphas)) {
  518.                 var isStacked = graphAxis && graphAxis.stackType && graphAxis.stackType !== 'none';
  519.                 if (isStacked || opts.type === 'column') {
  520.                     opts.fillAlphas = 0.7;
  521.                 } else {
  522.                     opts.fillAlphas = 0;
  523.                 }
  524.             }
  525.             if (angular.isUndefined(opts.lineThickness)) {
  526.                 opts.lineThickness = opts.type === 'column' ? 1.0 : 2.0;
  527.             }
  528.  
  529.             // using smoothing without equal spacing gives strange loopy lines due to bug in amCharts
  530.             // https://stackoverflow.com/questions/45863892/random-curves-in-js-chart-line-graph-by-amcharts
  531.             if (!chart.categoryAxis.equalSpacing && opts.type === 'smoothedLine') {
  532.                 opts.type = 'line';
  533.             }
  534.  
  535.             $.extend(true, graph, opts);
  536.         }
  537.        
  538.         function checkForAxisColors() {
  539.               if ($scope.options && $scope.options.valueAxes) {
  540.                   var customAxisColors = false;
  541.                   $scope.options.valueAxes.some(function(axis, index, array) {
  542.                       if (axis.color) {
  543.                             // Turn on custom color mode
  544.                             customAxisColors = true;
  545.                             return true;
  546.                       }
  547.                   });
  548.                   if (customAxisColors) {
  549.                       $element.addClass('amcharts-custom-color');
  550.                   } else {
  551.                       $element.removeClass('amcharts-custom-color');
  552.                   }
  553.               }
  554.         }
  555.  
  556.         function sortGraphs() {
  557.             chart.graphs.sort(function(a, b) {
  558.                 return a.graphNum - b.graphNum;
  559.             });
  560.         }
  561.  
  562.         function combine(output, newValues, valueField, point) {
  563.             if (!newValues) return;
  564.  
  565.             for (var i = 0; i < newValues.length; i++) {
  566.                 var value = newValues[i];
  567.                 var timestamp;
  568.                 if ($scope.timeFormat) {
  569.                     var m = $scope.timezone ? moment.tz(value.timestamp, $scope.timezone) : moment(value.timestamp);
  570.                     timestamp = m.format($scope.timeFormat);
  571.                 } else {
  572.                     timestamp = value.timestamp;
  573.                 }
  574.  
  575.                 if (!output[timestamp]) {
  576.                     output[timestamp] = {timestamp: timestamp};
  577.                 }
  578.                
  579.                 output[timestamp][valueField] = value.value;
  580.                 output[timestamp][valueField + '_rendered'] = value.rendered || pointValueToString(value.value, point);
  581.             }
  582.         }
  583.  
  584.         function updateValues() {
  585.             var values = $scope.timeFormat ? {} : [];
  586.  
  587.             for (var i = 1; i <= MAX_SERIES; i++) {
  588.                 var seriesValues = $scope['series' + i + 'Values'];
  589.  
  590.                 var point = getPointForGraph(i);
  591.                 var valueField = 'value_' + (point ? point.xid : i);
  592.                
  593.                 combine(values, seriesValues, valueField, point);
  594.             }
  595.  
  596.             // normalize sparse array or object into dense array
  597.             var output = [];
  598.             for (var timestamp in values) {
  599.                 output.push(values[timestamp]);
  600.             }
  601.  
  602.             // XXX sparse array to dense array doesnt result in sorted array
  603.             // manually sort here
  604.             if (output.length && typeof output[0].timestamp === 'number') {
  605.                 output.sort(function(a,b) {
  606.                     return a.timestamp - b.timestamp;
  607.                 });
  608.             }
  609.  
  610.             chart.dataProvider = output;
  611.             checkEqualSpacing();
  612.             chart.validateNow(true);
  613.         }
  614.  
  615.         function isAllUndefined(a) {
  616.             for (var i = 0; i < a.length; i++) {
  617.                 if (a[i] !== undefined) return false;
  618.             }
  619.             return true;
  620.         }
  621.        
  622.         function dataItemToText(dataItem) {
  623.             if (dataItem.dataContext) {
  624.                 var graph = dataItem.graph;
  625.  
  626.                 var value = extractField(dataItem.dataContext, graph.valueField);
  627.                 if (value) return value;
  628.                
  629. //                for (var i = dataItem.index - 1; i >= 0; i--) {
  630. //                    value = extractField(chart.dataProvider[i], graph.valueField);
  631. //                    if (value) return value;
  632. //                }
  633.             }
  634.             return '';
  635.         }
  636.  
  637.         function pointValueToString(pointValue,point){
  638.             if (point && typeof point.valueRenderer === 'function') {
  639.                 var rendered = point.valueRenderer(pointValue);
  640.                 if (rendered && rendered.text && typeof rendered.text === 'string') {
  641.                     return rendered.text;
  642.                 }
  643.             }
  644.            
  645.             if (typeof pointValue === 'number') {
  646.                 // convert to 3 fixed decimal places
  647.                 var numberString = pointValue.toFixed(3);
  648.                
  649.                 // dont display trailing zeros
  650.                 if (numberString.substr(-4) === '.000') {
  651.                     return numberString.slice(0, -4);
  652.                 } else if (numberString.substr(-2) === '00') {
  653.                     return numberString.slice(0, -2);
  654.                 } else if (numberString.substr(-1) === '0') {
  655.                     return numberString.slice(0, -1);
  656.                 } else {
  657.                     return numberString;
  658.                 }
  659.             }
  660.            
  661.             if (typeof pointValue === 'boolean') {
  662.                 return pointValue ? '1' : '0';
  663.             }
  664.            
  665.             return '' + pointValue;
  666.        
  667.         }
  668.        
  669.         function extractField(data, fieldName) {
  670.             var rendered = data[fieldName + '_rendered'];
  671.             if (rendered) return rendered;
  672.            
  673.             var value = data[fieldName];
  674.             if (value != null) {
  675.                 return pointValueToString(value);
  676.             }
  677.         }
  678.     }
  679.    
  680.     function defaultOptions() {
  681.         return {
  682.             type: 'serial',
  683.             theme: 'light',
  684.             addClassNames: true,
  685.             synchronizeGrid: true,
  686.             valueAxes: [{
  687.                 id: 'left',
  688.                 position: 'left',
  689.                 axisThickness: 2
  690.             },{
  691.                 id: 'right',
  692.                 position: 'right',
  693.                 axisThickness: 2
  694.             },{
  695.                 id: 'left-2',
  696.                 position: 'left',
  697.                 offset: 50,
  698.                 axisThickness: 2
  699.             },{
  700.                 id: 'right-2',
  701.                 position: 'right',
  702.                 offset: 50,
  703.                 axisThickness: 2
  704.             }],
  705.            
  706.             categoryAxis: {
  707.                 parseDates: true,
  708.                 minPeriod: 'fff',
  709.                 equalSpacing: false,
  710.                 dashLength: 1,
  711.                 minorGridEnabled: true,
  712.                 axisThickness: 0,
  713.                 dateFormats:[{period:'fff',format:'HH:mm:ss'},
  714.                                     {period:'ss',format:'HH:mm:ss'},
  715.                                     {period:'mm',format:'HH:mm:ss'},
  716.                                     {period:'hh',format:'HH:mm'},
  717.                                     {period:'DD',format:'MMM DD'},
  718.                                     {period:'WW',format:'MMM DD'},
  719.                                     {period:'MM',format:'MMM'},
  720.                                     {period:'YYYY',format:'YYYY'}],
  721.                 firstDayOfWeek: moment.localeData(moment.locale()).firstDayOfWeek()
  722.             },
  723.             chartCursor: {
  724.                     categoryBalloonDateFormat:'MMM DD HH:mm:ss',
  725.                     pan: true,
  726.                     valueLineEnabled: true,
  727.                     valueLineBalloonEnabled: true,
  728.                     cursorAlpha:1,
  729.                     cursorColor:'#258cbb',
  730.                     valueLineAlpha:0.2,
  731.                     valueZoomable:false
  732.             },
  733.             chartScrollbar: {
  734.                     oppositeAxis:false,
  735.                     offset:30,
  736.                     scrollbarHeight: 80,
  737.                     backgroundAlpha: 0,
  738.                     selectedBackgroundAlpha: 0.1,
  739.                     selectedBackgroundColor: '#888888',
  740.                     graphFillAlpha: 0,
  741.                     graphLineAlpha: 0.5,
  742.                     selectedGraphFillAlpha: 0,
  743.                     selectedGraphLineAlpha: 1,
  744.                     autoGridCount:true,
  745.                     hideResizeGrips:true,
  746.                     resizeEnabled:false,
  747.                     color:'#AAAAAA'
  748.                 },
  749.             startDuration: 0,
  750.             graphs: [],
  751.             plotAreaFillAlphas: 0.0,
  752.             categoryField: 'timestamp',
  753.             'export': {
  754.                 enabled: false,
  755.                 libs: {autoLoad: false},
  756.                 dateFormat: 'MMM D, YYYY HH:mm:ss',
  757.                 fileName: 'chart'
  758.             }
  759.         };
  760.     }
  761.    
  762.    
  763. }
  764. );
  765.  
  766. userModule.component('customchartcomponent', {
  767.     bindings: {
  768.         values: '<?',
  769.         end:'<?',
  770.         hours:'<?',
  771.         selected:'=?',
  772.     },
  773.     controller: ['$scope', '$element',
  774.     function($scope, $element) {
  775.        
  776.          //Define your own locale
  777.         moment.locale('et');
  778.        
  779.         const options = {
  780.                 "zoomOutText": "",
  781.                 "type": "serial",
  782.                 "theme": "light",
  783.                 "marginRight": 40,
  784.                 "marginLeft": 40,
  785.                 "autoMarginOffset": 20,
  786.                 "mouseWheelZoomEnabled":false,
  787.                 "dataProvider":[],
  788.                 "valueAxes": [{
  789.                     "id": "v1",
  790.                     "axisAlpha": 0,
  791.                     "position": "left",
  792.                     "ignoreAxisWidth":true
  793.                 }],
  794.                 "balloon": {
  795.                     "borderThickness": 1,
  796.                     "shadowAlpha": 0
  797.                 },
  798.                 "graphs": [{
  799.                     "id": "g1",
  800.                     "balloon":{
  801.                       "drop":true,
  802.                       "adjustBorderColor":false,
  803.                       "color":"#ffffff"
  804.                     },
  805.                     "bullet": "round",
  806.                     "bulletBorderAlpha": 1,
  807.                     "bulletColor": "#FFFFFF",
  808.                     "bulletSize": 5,
  809.                     "hideBulletsCount": 50,
  810.                     "lineThickness": 2,
  811.                     "title": "red line",
  812.                     "useLineColorForBulletBorder": true,
  813.                     "valueField": "value",
  814.                     "balloonText": "<span style='font-size:18px;'>[[value]]</span>"
  815.                 }],
  816.                 "chartScrollbar": {
  817.                     "graph": "g1",
  818.                     "oppositeAxis":false,
  819.                     "offset":30,
  820.                     "scrollbarHeight": 80,
  821.                     "backgroundAlpha": 0,
  822.                     "selectedBackgroundAlpha": 0.1,
  823.                     "selectedBackgroundColor": "#888888",
  824.                     "graphFillAlpha": 0,
  825.                     "graphLineAlpha": 0.5,
  826.                     "selectedGraphFillAlpha": 0,
  827.                     "selectedGraphLineAlpha": 1,
  828.                     "autoGridCount":true,
  829.                     "hideResizeGrips":true,
  830.                     "resizeEnabled":false,
  831.                     "color":"#AAAAAA"
  832.                 },
  833.                 "chartCursor": {
  834.                     "pan": true,
  835.                     "valueLineEnabled": true,
  836.                     "valueLineBalloonEnabled": true,
  837.                     "cursorAlpha":1,
  838.                     "cursorColor":"#258cbb",
  839.                     "limitToGraph":"g1",
  840.                     "valueLineAlpha":0.2,
  841.                     "categoryBalloonDateFormat":'MMM DD HH:mm:ss',
  842.                     "valueZoomable":false
  843.                 },
  844.                 "categoryField": "timestamp",
  845.                 "categoryAxis": {
  846.                     "dateFormats":[{period:'fff',format:'HH:mm:ss'},
  847.                                     {period:'ss',format:'HH:mm:ss'},
  848.                                     {period:'mm',format:'HH:mm:ss'},
  849.                                     {period:'hh',format:'HH:mm'},
  850.                                     {period:'DD',format:'MMM DD'},
  851.                                     {period:'WW',format:'MMM DD'},
  852.                                     {period:'MM',format:'MMM'},
  853.                                     {period:'YYYY',format:'YYYY'}],
  854.                     "minPeriod":"fff",                
  855.                     "parseDates": true,
  856.                     "dashLength": 1,
  857.                     "minorGridEnabled": true
  858.                 },
  859.                 "export": {
  860.                     "enabled": true
  861.                 }
  862.             }
  863.  
  864.         const chart = AmCharts.makeChart($element[0], options);
  865.  
  866.         chart.addListener('zoomed', event => {
  867.             if (angular.isArray(this.values)){
  868.                //console.log("This is zoomed");
  869.                 this.selected = [];
  870.                 let s = moment(chart.startDate).format('LLL');
  871.                 let e = moment(chart.endDate).format('LLL');
  872.                 this.selected.push({
  873.                    start : s,
  874.                    end : e
  875.                     });
  876.    
  877.             }
  878.            
  879.         });
  880.  
  881.         chart.addListener("dataUpdated", () => {
  882.             if (angular.isArray(chart.dataProvider) && typeof this.end !== "undefined"){
  883.  
  884.                 var e = moment(this.end);
  885.                 // Default zooming interval is 12 hours if not defined otherway
  886.                 var hourvar;
  887.                
  888.                 if (typeof this.hours !== "undefined"){
  889.                     hourvar = this.hours;
  890.                 }else{
  891.                     hourvar = 12;
  892.                 }
  893.                
  894.                 var s = moment(this.end).subtract(hourvar, 'hours');
  895.                 e = e.toDate();
  896.                 s = s.toDate();
  897.                 chart.zoomToDates(s, e);
  898.           }
  899.            
  900.         });
  901.  
  902.         chart.addListener("rendered", () => {
  903.            
  904.         });
  905.    
  906.  
  907.         $scope.$watch('$ctrl.values', () => {
  908.            let new_values = [];
  909.             if (angular.isArray(this.values)){
  910.                
  911.                 angular.forEach(this.values, function(value,key){
  912.                    
  913.                     let new_timestamp = moment(value.timestamp).valueOf();
  914.                     new_values.push({
  915.                         timestamp : new_timestamp,
  916.                         value:value.value
  917.                     });
  918.                
  919.                    
  920.                 });
  921.            
  922.                 chart.dataProvider = new_values;
  923.                 //console.log(new_values);
  924.                 chart.validateNow(true);    
  925.             }
  926.         }, true);
  927.        
  928.     }],
  929.  
  930. });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement