{"id":2140,"date":"2019-09-09T13:00:00","date_gmt":"2019-09-09T13:00:00","guid":{"rendered":"https:\/\/mindfusion.eu\/blog\/?p=2140"},"modified":"2021-01-23T16:13:35","modified_gmt":"2021-01-23T16:13:35","slug":"multi-series-line-chart-with-custom-tooltips","status":"publish","type":"post","link":"https:\/\/mindfusion.dev\/blog\/multi-series-line-chart-with-custom-tooltips\/","title":{"rendered":"Multi Series Line Chart With Custom ToolTips in JavaScript"},"content":{"rendered":"<p>In this blog post we will build a line chart with 4 different series and custom labels on both axes. The chart renders tooltips with custom formatting. You can see the chart online here:<\/p>\n<p><a title=\"JavaScript Chart With Custom ToolTips\" href=\"https:\/\/mindfusion.dev\/javascript-demo.html?sample=LineChartTooltips\"><img decoding=\"async\" title=\"JavaScript Chart With Multiple Series and ToolTips\" src=\"https:\/\/mindfusion.dev\/samples\/javascript\/chart\/line_chart_tooltips.png\" \/><\/a><\/p>\n<p><strong>I. Initial Setup<\/strong><\/p>\n<p>We start by creating a blank HTML page and there we initialize the HTML Canvas element that will be needed by the Js Chart library.<\/p>\n<pre id=\"line1\">&lt;<span class=\"start-tag\">canvas<\/span> <span class=\"attribute-name\">id<\/span>=\"<a class=\"attribute-value\">chart<\/a>\" <span class=\"attribute-name\">style<\/span>=\"<a class=\"attribute-value\">width: 100%; height: 100%; display: block;<\/a>\"&gt;<\/pre>\n<p>You can initialize the canvas as you want &#8211; there are no special requirements as to the size, position, scroll settings or anything else. What is important is that you add an id for that canvas &#8211; it will be used by the chart library. At the bottom of the page, right before the closing BODY tag we add a reference to the charting JavaScript files that represent the chart library:<\/p>\n<pre id=\"line1\">&lt;<span class=\"start-tag\">script<\/span> <span class=\"attribute-name\">type<\/span>=\"<a class=\"attribute-value\">text\/javascript<\/a>\" <span class=\"attribute-name\">src<\/span>=\"<a class=\"attribute-value\" href=\"view-source:https:\/\/mindfusion.dev\/blog\/multi-series-line-chart-with-custom-tooltips\/Scripts\/MindFusion.Common.js\">Scripts\/MindFusion.Common.js<\/a>\"&gt;&lt;\/<span class=\"end-tag\">script<\/span>&gt;\n<span id=\"line324\"><\/span>&lt;<span class=\"start-tag\">script<\/span> <span class=\"attribute-name\">type<\/span>=\"<a class=\"attribute-value\">text\/javascript<\/a>\" <span class=\"attribute-name\">src<\/span>=\"<a class=\"attribute-value\" href=\"view-source:https:\/\/mindfusion.dev\/blog\/multi-series-line-chart-with-custom-tooltips\/Scripts\/MindFusion.Charting.js\">Scripts\/MindFusion.Charting.js<\/a>\"&gt;&lt;\/<span class=\"end-tag\">script<\/span>&gt;<\/pre>\n<p>We also add a reference to another JavaScript file called LineChartTooltips.js. We haven&#8217;t created it yet, but this will be the file that will hold the JavaScript code for our chart.<\/p>\n<pre id=\"line1\">&lt;<span class=\"start-tag\">script<\/span> <span class=\"attribute-name\">type<\/span>=\"<a class=\"attribute-value\">text\/javascript<\/a>\" <span class=\"attribute-name\">src<\/span>=\"<a class=\"attribute-value\" href=\"view-source:https:\/\/mindfusion.dev\/blog\/multi-series-line-chart-with-custom-tooltips\/LineChartTooltips.js\">LineChartTooltips.js<\/a>\"&gt;<\/pre>\n<p>II. Initializing the Line Chart In the LineChartTooltips JavaScript file we first include a reference to the Intellisense file so we can use code completion.<\/p>\n<pre id=\"line1\">\/\/\/ &lt;<span class=\"start-tag\">reference<\/span> <span class=\"attribute-name\">path<\/span>=\"<a class=\"attribute-value\">Scripts\/jspack-vsdoc.js<\/a>\"&gt;&lt;\/<span class=\"end-tag\">reference<\/span>&gt;<\/pre>\n<p>Then we add mappings to the namespaces that we want to use:<\/p>\n<pre>var Controls = Charting.Controls;\nvar Collections = Charting.Collections;\nvar DateTimeSeries = Charting.DateTimeSeries;\nvar Drawing = Charting.Drawing;\nvar ToolTip = Charting.ToolTip;\n<\/pre>\n<p>Now we create the JavaScript chart object. We need a reference to the HTML canvas element, which we get using its id:<\/p>\n<pre>var chartEl = document.getElementById('chart');\nchartEl.width = chartEl.offsetParent.clientWidth;\nchartEl.height = chartEl.offsetParent.clientHeight;\n<\/pre>\n<p>We use the clientWidth and clientHeight properties of the offsetElement for the chart to give the chart its size.<\/p>\n<p>Next we create the <a title=\"JavaScript Scheduler API Reference: LineChart\" href=\"https:\/\/www.mindfusion.dev\/onlinehelp\/chart.javascript\/index.htm?T_MindFusion_Charting_Controls_LineChart.htm\">LineChart<\/a> control and set its title and subtitle.<\/p>\n<pre>\/\/ create the chart\nvar lineChart = new Controls.LineChart(chartEl);\nlineChart.title = \"Women as a percentage in all S&amp;E occupations\";\nlineChart.subtitle = \"1993-2010\";\n<\/pre>\n<p><strong>III. Labels<\/strong><\/p>\n<p>The labels for the X and Y axes are set with two lists:<\/p>\n<pre>var xlabels = new Collections.List([\n    \"1993\", \"1995\", \"1997\", \"1999\", \"2003\", \"2006\",\n    \"2008\", \"2010\"]);\n\nvar ylabels = new Collections.List([\n    \"0%\", \"10%\", \"20%\", \"30%\", \"40%\", \"50%\",\n    \"60%\", \"70%\"]);\n<\/pre>\n<p>By default the labels at the axes are the intervals. We can replace them with the labels of a given chart series by using the <a title=\"JavaScript Chart API Reference: supportedLabels\" href=\"https:\/\/www.mindfusion.dev\/onlinehelp\/chart.javascript\/index.htm?P_MindFusion_Charting_Series_supportedLabels_0_0.htm\">supportedLabels<\/a> property. This property tells the control at which chart element the labels of the series should be rendered &#8211; X or Y axis, tooltip, data labels etc. The members are from the <a title=\"JavaScript Chart API Reference: LabelKinds\" href=\"https:\/\/www.mindfusion.dev\/onlinehelp\/chart.javascript\/index.htm?T_MindFusion_Charting_LabelKinds_0.htm\">LabelKinds<\/a> enumeration.<\/p>\n<p>The LineChart control uses series that support X and Y values. The best match is the Series2D class. This class supports one list with labels, which are always drawn at the data points. The easiest thing for us to do is to customize the <a title=\"JavaScript Chart API Reference: Series2D\" href=\"https:\/\/www.mindfusion.dev\/onlinehelp\/chart.javascript\/index.htm?T_MindFusion_Charting_Series2D_0.htm\">Series2D<\/a> and make it accept two lists with labels, which we will show them on both axes. Here is how we create the custom class by inheriting from <a title=\"JavaScript Chart API Reference: Series2D\" href=\"https:\/\/www.mindfusion.dev\/onlinehelp\/chart.javascript\/index.htm?T_MindFusion_Charting_Series2D_0.htm\">Series2D<\/a><\/p>\n<pre>SeriesWithAxisLabels = function (xValues, yValues, xLabels, yLabels) {\n    this.yLabels = yLabels;\n    Charting.Series2D.apply(this, [xValues, yValues, xLabels]);\n};\n\nSeriesWithAxisLabels.prototype = Object.create(Charting.Series2D.prototype);\n<\/pre>\n<p>Our custom class is called SeriesWithAxisLabels. It accepts two lists with labels in the constructor. With one of them we call the constructor of the base class. The other we assign to a new property called yLabels.<\/p>\n<p>Now we need to override the getLabel method and return the right label for the X and Y axis.<\/p>\n<pre>SeriesWithAxisLabels.prototype.getLabel = function (index, kind) {\n    if ((kind &amp; Charting.LabelKinds.XAxisLabel) != 0 &amp;&amp; this.labels)\n        return this.labels.items()[index];\n\n    if ((kind &amp; Charting.LabelKinds.YAxisLabel) != 0 &amp;&amp; this.yLabels)\n        return this.yLabels.items()[index];\n   \n    return \"\";\n};\n<\/pre>\n<p>The getLabel method is responsible for providing the correct label according to the kind of labels that is requested. Here we check if we are asked for a label at the X or Y axis and return the label with the correct index from the xLabels or yLabels arrays. Here is how we create that series, which serves only to provide labels for the axes:<\/p>\n<pre>var series0 = new SeriesWithAxisLabels(\n    new Collections.List([1, 2, 3, 4, 5, 6, 7, 8]),\n    new Collections.List([0, 10, 20, 30, 40, 50, 60, 70]),\n    xlabels, ylabels\n);\nseries0.supportedLabels = Charting.LabelKinds.XAxisLabel | Charting.LabelKinds.YAxisLabel;\nlineChart.series.add(series0);\n<\/pre>\n<p>Note that the data for the X and Y values of series0 corresponds to the positions on the axes where the labels should be rendered.<\/p>\n<p><strong>IV. Data<\/strong><\/p>\n<p>The data for the chart is provided by two series. They are also of type <a title=\"JavaScript Chart API Reference: Series2D\" href=\"https:\/\/www.mindfusion.dev\/onlinehelp\/chart.javascript\/index.htm?T_MindFusion_Charting_Series2D_0.htm\">Series2D<\/a> However, we do not want them to render the labels at the data points, which is their default behaviour. We would customize once again the <a title=\"JavaScript Chart API Reference: Series2D\" href=\"https:\/\/www.mindfusion.dev\/onlinehelp\/chart.javascript\/index.htm?T_MindFusion_Charting_Series2D_0.htm\">Series2D<\/a> class and make the labels be used for tooltips and not the data points.<\/p>\n<p>We define a new SeriesWithToolTip class that overrides <a title=\"JavaScript Chart API Reference: Series2D\" href=\"https:\/\/www.mindfusion.dev\/onlinehelp\/chart.javascript\/index.htm?T_MindFusion_Charting_Series2D_0.htm\">Series2D<\/a><\/p>\n<pre>SeriesWithToolTip = function (xValues, yValues, labels) { \n    Charting.Series2D.apply(this, [xValues, yValues, labels]);\n};\n\nSeriesWithToolTip.prototype = Object.create(Charting.Series2D.prototype);\n<\/pre>\n<p>The difference is the <a title=\"JavaScript Chart API Reference: getLabel\" href=\"https:\/\/www.mindfusion.dev\/onlinehelp\/chart.javascript\/index.htm?M_MindFusion_Charting_Series2D_getLabel_2_Number_LabelKinds.htm\">getLabel<\/a> method. When asked for a label for the tooltip it returns the label at the given position from the series&#8217; labels list:<\/p>\n<pre>SeriesWithToolTip.prototype.getLabel = function (index, kind) {\n    if ((kind &amp; Charting.LabelKinds.ToolTip) != 0 &amp;&amp; this.labels)\n        return this.labels.items()[index];   \n\n    return Charting.Series2D.prototype.getLabel.apply(this, [index, kind]);\n};\n<\/pre>\n<p>We create a data series from the SeriesWithToolTip kind this way:<\/p>\n<pre>\/\/first series\nvar series1 = new SeriesWithToolTip(\n    new Collections.List([1, 2, 3, 4, 5, 6, 7, 8]),\n    new Collections.List([21.3, 21.5, 21.7, 23, 26.3, 26.1, 26.3, 27.5])\n);\n\nseries1.title = \"All S&amp;E occupations\";\nvar tooltips = new Collections.List();\n\nfor (let step = 0; step &lt; series1.yData.count(); step++) {\n    tooltips.add(series1.title + \" for \" + xlabels.items()[step] + \": \" +\n        series1.yData.items()[step] + \"%\");\n}\nseries1.labels = tooltips;\nseries1.supportedLabels = Charting.LabelKinds.ToolTip;\nlineChart.series.add(series1);\n<\/pre>\n<p>We generate the tooltip in a list, because we want the text to combine data from the xLabels and its yData list.<\/p>\n<p><strong>V. Styling the Chart<\/strong><\/p>\n<p>the JavaScript Chart library supports several styles to be applied on the chart depending on what you want to achieve. In our case the best choice is the <a title=\"JavaScript Chart API Reference: PerSeriesStyle\" href=\"https:\/\/www.mindfusion.dev\/onlinehelp\/chart.javascript\/index.htm?T_MindFusion_Charting_PerSeriesStyle_0.htm\">PerSeriesStyle<\/a> class, which colours all the elements of a <a title=\"JavaScript Chart API Reference: Series\" href=\"https:\/\/www.mindfusion.dev\/onlinehelp\/chart.javascript\/index.htm?T_MindFusion_Charting_Series_0.htm\">Series<\/a> with the subsequent brush from its strokes and fills collections.<\/p>\n<pre>\/\/ create line brushes\nvar firstBrush = new Drawing.Brush(\"transparent\");\nvar secondBrush = new Drawing.Brush(\"#EA3F36\");\nvar thirdBrush = new Drawing.Brush(\"#1A3D95\"); \nvar fourthBrush = new Drawing.Brush(\"#717173\");\nvar fifthBrush = new Drawing.Brush(\"#407D39\");\n\nvar style = new Charting.PerSeriesStyle();\nstyle.fills = style.strokes = new Collections.List([firstBrush, secondBrush, thirdBrush, fourthBrush, fifthBrush]);\nstyle.strokeDashStyles = new Collections.List([Drawing.DashStyle.Dash, Drawing.DashStyle.Dash,\nDrawing.DashStyle.Dash, Drawing.DashStyle.Dash, Drawing.DashStyle.Dash]);\nstyle.strokeThicknesses = new Collections.List([2, 2, 2, 2, 2]);\nlineChart.plot.seriesStyle = style;\n<\/pre>\n<p>The PerSeriesStyle class also provides us with properties to specify the DashStyle and the strokeThickness of the brushes.<\/p>\n<p>The styling of the axes and the fonts is done via the properties of the <a title=\"JavaScript Chart API Reference: Theme\" href=\"https:\/\/www.mindfusion.dev\/onlinehelp\/chart.javascript\/index.htm?T_MindFusion_Charting_Theme_1.htm\">Theme<\/a> class. Each chart has a <a title=\"JavaScript Chart API Reference: theme\" href=\"https:\/\/www.mindfusion.dev\/onlinehelp\/chart.javascript\/index.htm?P_MindFusion_Charting_RenderContext_theme_0_0.htm\">theme<\/a> property of type Theme. You can use it to customize many properties of the chart:<\/p>\n<pre>lineChart.legendTitle = \"\";\nlineChart.gridType = Charting.GridType.Horizontal;\nlineChart.theme.axisTitleFontSize = 14;\nlineChart.theme.axisLabelsFontSize = 12;\nlineChart.theme.subtitleFontStyle = Charting.Drawing.FontStyle.Bold;\nlineChart.theme.titleFontStyle = Charting.Drawing.FontStyle.Bold;\nlineChart.theme.subtitleFontSize = 16;\nlineChart.theme.dataLabelsFontSize = 12;\n<\/pre>\n<p>Note the dataLabelsFontSize property here. It regulates the font not only for the data labels but for the labels of the legend. That is why we set it, though we do not render data labels. There are several dataLabels properties like dataLabelsFontName, which customize different aspects of the labels at chart series and legend.<\/p>\n<p><strong>VI. Legend<\/strong><\/p>\n<p>You can show the legend with <a title=\"JavaScript Chart API Reference: showLegend\" href=\"https:\/\/www.mindfusion.dev\/onlinehelp\/chart.javascript\/index.htm?P_MindFusion_Charting_Controls_Chart_showLegend_0.htm\">showLegend<\/a> property, which is true by default. The legendTitle property sets the title of the legend, which we set to an epty string. The labels for each series are taken from the series&#8217; title property:<\/p>\n<pre>lineChart.legendTitle = \"\";\n\nseries1.title = \"All S&amp;E occupations\";\n.................\nseries2.title = \"Computer\/mathematical scientists\";\n..................\nseries3.title = \"Engineers\";\n<\/pre>\n<p>We can customize the background and border of the legend through properties of the theme or the <a title=\"JavaScript Chart API Reference: LegendRenderer\" href=\"https:\/\/www.mindfusion.dev\/onlinehelp\/chart.javascript\/index.htm?T_MindFusion_Charting_LegendRenderer_0.htm\">LegendRenderer<\/a>:<\/p>\n<pre>lineChart.legendRenderer.background = new Drawing.Brush(\"#f2f2f2\");\nlineChart.legendRenderer.borderStroke = new Drawing.Brush(\"#c0c0c0\");\n<\/pre>\n<p><strong>VII. ToolTips<\/strong><\/p>\n<p>The tooltips are automatically rendered when the user hovers over a data point. We make the data points visible by setting <a title=\"JavaScript Chart API Reference: showScatter\" href=\"https:\/\/www.mindfusion.dev\/onlinehelp\/chart.javascript\/index.htm?P_MindFusion_Charting_Controls_BiaxialChart_showScatter_0.htm\">showScatter<\/a> to true:<\/p>\n<pre>lineChart.showScatter = true;\n<\/pre>\n<p>Then we set different properties of the TooltTip class to achieve the desired look of the tooltips:<\/p>\n<pre>ToolTip.brush = new Drawing.Brush(\"#fafafa\");\nToolTip.pen = new Drawing.Pen(\"#9caac6\");\nToolTip.textBrush = new Drawing.Brush(\"#717173\");\nToolTip.horizontalPadding = 6;\nToolTip.verticalPadding = 4;\nToolTip.horizontalOffset = -6;\nToolTip.verticalOffset = -4;\nToolTip.font = new Charting.Drawing.Font(\"Arial\", 12, Charting.Drawing.FontStyle.Bold);\n<\/pre>\n<p>The <a title=\"JavaScript Chart API Reference: ToolTip\" href=\"https:\/\/www.mindfusion.dev\/onlinehelp\/chart.javascript\/index.htm?T_MindFusion_Charting_ToolTip_0.htm\">ToolTip<\/a> class is a static class and we can set the properties directly.<\/p>\n<p>At the end, we should always call draw() to see the chart correctly rendered on the screen:<\/p>\n<pre>lineChart.draw();\n<\/pre>\n<p>You can download the sample with the JavaScript chart libraries and the Intellisense file from this link:<\/p>\n<p><a title=\"JavaScript Chart Sample\" href=\"https:\/\/mindfusion.dev\/samples\/javascript\/chart\/JsLineChartTooltips.zip\">https:\/\/mindfusion.dev\/samples\/javascript\/chart\/JsLineChartTooltips.zip<\/a><\/p>\n<p><i>About Charting for JavaScript:<\/i> MindFusion library for interactive charts and gauges. It supports all common chart types including 3D bar charts. Charts can have a grid, a legend, unlimitd number of axes and series. Scroll, zoom and pan are supported out of the box. You can easily create your own chart series by implementing the Series interface.<br \/>\nThe gauges library is part of Charting for JavaScript. It supports oval and linear gauge with several types of labels and ticks. Various samples show you how the implement the gauges to create and customize all popular gauge types: car dashboard, clock, thermometer, compass etc. Learn more about Charting and Gauges for JavaScript at <a title=\"JavaScript Chart Library\" href=\"https:\/\/mindfusion.dev\/javascript-chart.html\">https:\/\/mindfusion.dev\/javascript-chart.html<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this blog post we will build a line chart with 4 different series and custom labels on both axes. The chart renders tooltips with custom formatting. You can see the chart online here: I. Initial Setup We start by &hellip; <a href=\"https:\/\/mindfusion.dev\/blog\/multi-series-line-chart-with-custom-tooltips\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[61,513,74],"tags":[562,425,443,424,561],"class_list":["post-2140","post","type-post","status-publish","format-standard","hentry","category-charting-2","category-javascript","category-sample-code","tag-custom-tooltips","tag-javascript-chart","tag-javascript-chart-library","tag-js-chart","tag-multiple-chart-series"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p3RlKs-yw","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/posts\/2140","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/comments?post=2140"}],"version-history":[{"count":18,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/posts\/2140\/revisions"}],"predecessor-version":[{"id":2631,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/posts\/2140\/revisions\/2631"}],"wp:attachment":[{"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/media?parent=2140"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/categories?post=2140"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/tags?post=2140"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}