Using JavaScript to get CSS properties

Posted by ryansouthgate on 27 Jul 2015

On a work project using Highcharts, we needed the colours of each series to be “configurable”. Unfortunately on first glance, Highcharts doesn’t support getting colours from CSS out of the box. Instead we need write some code to allow us to use JavaScript to get CSS properties, specifically the colour property and then give those colours to Highcharts to apply to a series.

When creating a chart using Highcharts, we can set the colour of a series through code (when instantiating a chart), as below:

plotOptions: {
   series: {
      id: 'moneySeries',
      type: 'column',
      name: 'Money',
      data: moneyData,
      color: '#ff0000' //red
   }
}

If we are getting data dynamically (after chart creation), then when adding the series using addSeries we can specify the colour like:

chart.addSeries({ 
   id: 'moneySeries', 
   type: 'column', 
   name: 'Money', 
   data: moneyData, 
   color: '#ff0000' //red 
});

This is great, however when someone requests that the colour for the money series be changed to green, then we have to ship them a different version of the javascript file which creates the chart.

This is not great practise, js files should be for code and functionality, ideally we’d have a separate file specifying the colours to be used for the series. Unfortunately (as of today) Highcharts will only allow you to specify the colours in Hex format (e.g. ‘#ff0000’) or RGB/RGBA(‘rgb(255,0,0)’) through code, and it wont let you specify a css class to pull the colour from.

So we have to do it ourselves.

I’ve written this function, which check’s the existence of the specified css file, caches the css properties (by creating a variable on the window), and returns the colour of the class you’ve asked for.

function getChartStyle(cssFilename, chartCssCachePropName, className){ 
   // Check to see if we have the css already cached (from a previous call), if not go and search for the css "sheet" 
   if (window[chartCssCachePropName] == null || window[chartCssCachePropName].cssRules == null) { 
      for (var i = 0; i < document.styleSheets.length; i++) {
         if (endsWith(document.styleSheets[i].href, cssFilename)) { 
            window[chartCssCachePropName] = document.styleSheets[i]; 
            break; 
         } 
      }
   } 

   if (window[chartCssCachePropName] === null) {
      throw "Css (with href [" + cssFilename + "]) not found on page. Cannot get chart series colours."; 
   } 
   
   for (var x = 0; x < window[chartCssCachePropName].cssRules.length; x++) {
      if (window[chartCssCachePropName].cssRules[x].selectorText == '.' + className) {
         // Found the css property, get the colour (could also swap this out and pass it in on the method params
         return window[chartCssCachePropName].cssRules[x].style.color;
      } 
   }
}; 

function endsWith(str, suffix) { 
   if (str != null) { 
      return str.indexOf(suffix, str.length - suffix.length) !== -1; 
   } 
   return false; 
};

The function could be changed to allow you to specify the name of the property you wish to query for, however I’ve just left it to colour (for now).

Using the function

var moneyColour = getChartStyle("chart-series.css", "moneyChart", "moneyseries");

with the css

.moneyseries{ color: #00FF00; }

Would give us the colour green.

Now that we have used JavaScript to get CSS properties, we can pass that colour to Highcharts.

chart.addSeries({ id: 'moneySeries', type: 'column', name: 'Money', data: moneyData, color: moneyColour });
A few sources seem to say that attaching global variables to the window is “bad practise”, however I believe if you name them appropriately and try to keep them to a minimum, then you’re safe.

Here is a working Plunk

If you’ve got any ideas for improvements then hit me up in the comments.



comments powered by Disqus