| // Copyright (c) 2000-2019 Ericsson Telecom AB Telecom AB // |
| // All rights reserved. This program and the accompanying materials are made available under the // |
| // terms of the Eclipse Public License v2.0 which accompanies this distribution, and is available at // |
| // https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html // |
| /////////////////////////////////////////////////////////////////////////////////////////////////////// |
| function CView_Chart(p_viewmodels, p_mainId, p_parentId, p_data) {
|
| "use strict";
|
|
|
| /** constructor */
|
|
|
| var v_viewmodel = ViewUtils.getViewmodelsFromExpectedInterface(p_viewmodels, CView_Chart)[0];
|
| var v_conditionViewmodel = ViewUtils.getViewmodelsFromExpectedInterface(p_viewmodels, CView_Chart)[1];
|
| var v_mainId = p_mainId;
|
| var v_parentId = p_parentId;
|
| var v_customData = p_data;
|
|
|
| var v_chart;
|
|
|
| var v_this = this;
|
|
|
| /** public functions */
|
|
|
| this.applicationCreated = function() {
|
| if (v_viewmodel != undefined) {
|
| $("#" + v_parentId).append(getHtml());
|
|
|
| var data = [];
|
| var options = {
|
| series: {
|
| lines: {
|
| steps: false,
|
| fill: false
|
| },
|
| bars: {
|
| align: 'center',
|
| fill: 1,
|
| lineWidth: 0
|
| }
|
| },
|
| xaxis: {
|
| panRange: [0, 0],
|
| zoomRange: [5, null]
|
| },
|
| yaxis: {
|
| panRange: [0, 0],
|
| zoomRange: [5, null]
|
| },
|
| legend: {
|
| show: true,
|
| backgroundOpacity: 0.5,
|
| noColumns: 1
|
| },
|
| grid: {
|
| autoHighlight: true,
|
| hoverable: true,
|
| borderWidth: 0,
|
| margin: {}
|
| }
|
| };
|
|
|
| if (v_customData.type == "timeseries") {
|
| options.xaxis.mode = "time";
|
| options.xaxis.timezone = "browser";
|
| options.xaxis.timeformat = "%H:%M:%S";
|
| //options.grid.margin.bottom = 10;
|
| } else if (v_customData.type == "distribution") {
|
| options.grid.margin.bottom = 80;
|
| $("#" + v_mainId).addClass("RotatedXAxis");
|
| }
|
|
|
| if (v_customData.yTicksFormat == "percent") {
|
| options.yaxis.tickFormatter = tickFormatterPercent;
|
| } else if (v_customData.yTicksFormat == "data") {
|
| options.yaxis.tickFormatter = tickFormatterData;
|
| } else if (v_customData.yTicksSuffix != undefined) {
|
| options.yaxis.tickFormatter = tickFormatterCustom;
|
| }
|
|
|
| if (v_customData.zoomAndPan !== false) {
|
| options.zoom = {interactive: true};
|
| options.pan = {interactive: true};
|
| }
|
| |
| if ($("#" + v_mainId).width() == 0) { |
| $("#" + v_mainId).css("width", "1px"); |
| } |
|
|
| v_chart = $.plot($("#" + v_mainId), data, options);
|
|
|
| if (v_customData.title != undefined) {
|
| v_chart.hooks.drawOverlay.push(function(plot, cvs) {
|
| if(!plot) {
|
| return;
|
| }
|
|
|
| var cvsWidth = cvs.canvas.width / 2;
|
| var text = v_customData.title;
|
| cvs.font = "bold 16px Open Sans";
|
| cvs.fillStyle = "#666666";
|
| cvs.textAlign = "center";
|
| cvs.globalAlpha = "0.8";
|
| cvs.fillText(text, cvsWidth, 30);
|
| return cvs;
|
| });
|
| }
|
|
|
| setupCallbacks();
|
| }
|
| };
|
|
|
| this.refresh = function(p_fullRefresh) {
|
| if (v_viewmodel != undefined && ViewUtils.checkVisibility(v_conditionViewmodel, v_mainId)) {
|
| var chartData = v_viewmodel.getChartData();
|
| if (chartData.dataSets.length > 0) { |
| $("#" + v_mainId).css("width", "100%");
|
| $("#" + v_mainId).removeClass("hidden");
|
| v_chart.getAxes().xaxis.options.ticks = chartData.ticks;
|
| if (v_customData.zoomAndPan !== false) {
|
| setNavigationRanges(chartData.navigationRanges);
|
| }
|
|
|
| v_chart.setData(chartData.dataSets);
|
|
|
| v_chart.setupGrid();
|
| v_chart.draw();
|
|
|
| updateLegend(chartData.dataSets.length);
|
|
|
| if (v_customData.showValues) {
|
| createLabelsAtTop();
|
| }
|
| } else {
|
| $("#" + v_mainId).addClass("hidden");
|
| }
|
| }
|
| };
|
|
|
| /** private functions */
|
|
|
| function tickFormatterPercent(val, axis) {
|
| return val.toFixed(axis.tickDecimals) + "%";
|
| }
|
|
|
| function tickFormatterData(val, axis) {
|
| if (val > 1000) {
|
| return (val / 1000).toFixed(axis.tickDecimals) + " MB";
|
| } else {
|
| return val.toFixed(axis.tickDecimals) + " KB";
|
| }
|
| }
|
|
|
| function tickFormatterCustom(val, axis) {
|
| return val.toFixed(axis.tickDecimals) + v_customData.yTicksSuffix;
|
| }
|
|
|
| function setNavigationRanges(ranges) {
|
| var xAxis = v_chart.getAxes().xaxis;
|
| var yAxis = v_chart.getAxes().yaxis;
|
|
|
| xAxis.options.panRange[0] = ranges.x.pan.min;
|
| xAxis.options.panRange[1] = ranges.x.pan.max;
|
| xAxis.options.zoomRange[0] = ranges.x.zoom.min;
|
| xAxis.options.zoomRange[1] = ranges.x.zoom.max;
|
|
|
| yAxis.options.panRange[0] = ranges.y.pan.min;
|
| yAxis.options.panRange[1] = ranges.y.pan.max;
|
| yAxis.options.zoomRange[0] = ranges.y.zoom.min;
|
| yAxis.options.zoomRange[1] = ranges.y.zoom.max;
|
| }
|
|
|
| function createLabelsAtTop() {
|
| var ctx = v_chart.getCanvas().getContext("2d");
|
| var dataSets = v_chart.getData();
|
| for (var j = 0; j < dataSets.length; ++j) {
|
| if (v_viewmodel.isSeriesVisible(j)) {
|
| var data = dataSets[j].data;
|
| var xaxis = v_chart.getXAxes()[0];
|
| var yaxis = v_chart.getYAxes()[0];
|
| var offset = v_chart.getPlotOffset();
|
| ctx.fillStyle = dataSets[j].color;
|
| for (var i = 0; i < data.length; i++){
|
| var text = data[i][1] + '';
|
| var metrics = ctx.measureText(text);
|
| var xPos = (xaxis.p2c(data[i][0])+offset.left) - metrics.width / 2;
|
| var yPos = yaxis.p2c(data[i][1]) + offset.top - 5;
|
| ctx.fillText(text, xPos, yPos);
|
| }
|
| }
|
| }
|
| }
|
|
|
| function getHtml() {
|
| var height = "400px";
|
| if (v_customData.height != undefined) {
|
| height = v_customData.height;
|
| }
|
|
|
| var width = "800px";
|
| if (v_customData.width != undefined) {
|
| width = v_customData.width;
|
| }
|
|
|
| return '<div id="' + v_mainId + '" class="BasicChart" style="width: ' + width + '; height: ' + height + ';"></div>';
|
| }
|
|
|
| function updateLegend(numberOfEntries) {
|
| v_chart.getOptions().legend.noColumns = Math.ceil(numberOfEntries / 15);
|
|
|
| var counter = 0;
|
| var rows = $("#" + v_mainId + " .legend tr");
|
| for (var i = 0; i < rows.length; ++i) {
|
| var cols = $(rows[i]).find("td");
|
| for (var j = 0; j < cols.length; ++j) {
|
| if (j % 2 == 1) {
|
| if (v_viewmodel.isSeriesVisible(counter)) {
|
| $(cols[j]).removeClass("BasicChart_SeriesDisabled");
|
| } else {
|
| $(cols[j]).addClass("BasicChart_SeriesDisabled");
|
| }
|
| ++counter;
|
| }
|
| }
|
| }
|
| }
|
|
|
| function resetNavigation() {
|
| var axes = v_chart.getAxes();
|
| var xaxis = axes.xaxis.options;
|
| var yaxis = axes.yaxis.options;
|
| xaxis.min = null;
|
| xaxis.max = null;
|
| yaxis.min = null;
|
| yaxis.max = null;
|
|
|
| v_chart.setupGrid();
|
| v_chart.draw();
|
| }
|
|
|
| function saveAsImage() {
|
| html2canvas(document.getElementById(v_mainId), {
|
| onrendered: function(canvas) {
|
| var dataURL = canvas.toDataURL('image/png');
|
| var html = '<a href="' + dataURL + '" download="chart.png" id="chart_download">DOWNLOAD</a>';
|
| $("body").append(html);
|
| $("#chart_download")[0].click();
|
| $("#chart_download").remove();
|
| }
|
| });
|
| }
|
|
|
| function setupCallbacks() {
|
| $("#" + v_mainId).on("plothover", function(event, pos, data) {
|
| if (data != undefined) {
|
| if (v_customData.type == "timeseries") {
|
| $("#" + v_mainId).prop("title", data.series.label + "\nx: " + new Date(data.datapoint[0]) + "\ny: " + data.datapoint[1]);
|
| } else {
|
| $("#" + v_mainId).prop("title", data.series.label + "\n" + data.datapoint[1]);
|
| }
|
| }
|
| });
|
|
|
| $("#" + v_mainId).on("click", ".legend td", function(a, b, c) {
|
| var index = $(this).index();
|
| var parent = $(this).parent();
|
| var numberOfColumns = v_chart.getOptions().legend.noColumns;
|
| var parentIndex = parent.index();
|
|
|
| var seriesIndex = parentIndex * numberOfColumns + Math.floor(index / 2);
|
|
|
| v_viewmodel.toggleSeries(seriesIndex);
|
| v_this.refresh();
|
| });
|
|
|
| $("#" + v_mainId).on('contextmenu', function(event) {
|
| var customDataForMenu = {
|
| "offset": {top: event.clientY - 5, left: event.clientX - 5}
|
| };
|
| var id = v_mainId + "_ContextMenu";
|
| var contextMenu = new CView_ContextMenu([{
|
| "getMenuElements": function() {
|
| return [{
|
| "text": "Reset Navigation",
|
| "callback": resetNavigation
|
| },
|
| {
|
| "text": "Save As Image",
|
| "callback": saveAsImage
|
| }];
|
| }
|
| }], id, v_parentId, customDataForMenu);
|
| contextMenu.applicationCreated();
|
| ViewUtils.applyCss(customDataForMenu, id);
|
|
|
| event.preventDefault();
|
| return false;
|
| });
|
| }
|
| }
|
|
|
| CView_Chart.getHelp = function() {
|
| return "A chart view. Make sure that the chart has a width and a height, otherwise it will not work. By default they are set to 800px and 400px respectively. Percentages will only work when the browser can calculate them.";
|
| };
|
|
|
| CView_Chart.expectsInterface = function() {
|
| return [
|
| {
|
| "mandatory": ["getChartData", "toggleSeries", "isSeriesVisible"]
|
| },
|
| {
|
| "optional": ["getState"]
|
| }
|
| ];
|
| };
|
|
|
| CView_Chart.getCustomDataSchema = function() {
|
| var schema = {
|
| "$schema": "http://json-schema.org/draft-04/schema#",
|
| "title": "Custom data for CView_Chart",
|
| "type": "object",
|
| "properties": {
|
| "width": {
|
| "type": "string",
|
| "description": "The width of the chart.",
|
| "default": "800px"
|
| },
|
| "height": {
|
| "type": "string",
|
| "description": "The height of the chart.",
|
| "default": "400px"
|
| },
|
| "showValues": {
|
| "type": "boolean",
|
| "format": "checkbox",
|
| "description": "Whether the values are displayed.",
|
| "default": true
|
| },
|
| "type": {
|
| "type": "string",
|
| "description": "The chart type.",
|
| "enum": ["timeseries", "distribution"],
|
| "default": "timeseries"
|
| },
|
| "yTicksFormat": {
|
| "type": "string",
|
| "description": "The format of the y axis labels. To use a custom one, use yTicksSuffix.",
|
| "enum": ["percent", "data"]
|
| },
|
| "yTicksSuffix": {
|
| "type": "string",
|
| "description": "The custom suffix of the y axis labels."
|
| },
|
| "zoomAndPan": {
|
| "type": "boolean",
|
| "format": "checkbox",
|
| "description": "Whether the chart can be zoomed and panned (default is true).",
|
| "default": false
|
| },
|
| "title": {
|
| "type": "string",
|
| "description": "The title of the chart."
|
| }
|
| },
|
| "additionalProperties": false,
|
| "required": ["type"]
|
| };
|
| $.extend(true, schema, ViewUtils.commonViewSchema);
|
| return schema;
|
| };
|
|
|
| //# sourceURL=WebApplicationFramework\Views\View_Chart.js |