Matteo-SoftNet
Matteo-SoftNet

Reputation: 531

Highcharts CSV export changes the chart JS object

I am using this js function to export CSV from an Highcharts chart. I am already using the latest version of Highcharts (3.0.7). The CSV is exported correctly, the problem with this code is that AFTER exporting a 3d chart the x-axis, in some cases, is modified as if the Highcharts javascript object had been changed. However, the code below doesn't touch (at least this is what I think) the real Highcharts object.

After some tests, I discovered that commenting this if-block:

if (xAxis.categories) {
    columns.push(xAxis.categories);
    columns[0].unshift("");
}

prevents the x-axis to be updated after the export, but at the same time this obviously breaks the exported CSV.

How is this possible?

(function (Highcharts) {

    // Options
    var itemDelimiter = ';',  // use ';' for direct import to Excel
        lineDelimiter = '\n';

    var each = Highcharts.each;
    Highcharts.Chart.prototype.getCSV = function () {
        var xAxis = this.options.xAxis[0],
            columns = [],
            line,
            csv = "",
            row,
            col;

        if (xAxis.categories) {
            columns.push(xAxis.categories);
            columns[0].unshift("");
        }

        each(this.series, function (v){
            columns.push(v.yData);
            columns[columns.length - 1].unshift(v.name);
        });

        // Transform the columns to CSV
        for (row = 0; row < columns[0].length; row++) {
            line = [];
            for (col = 0; col < columns.length; col++) {
                line.push(columns[col][row]);
            }
            csv += line.join(itemDelimiter) + lineDelimiter;
        }
        return csv;
    };   

    // Now we want to add "Download CSV" to the exporting menu. We post the CSV
    // to a simple PHP script that returns it with a content-type header as a 
    // downloadable file.
    // The source code for the PHP script can be viewed at 
    // https://raw.github.com/highslide-software/highcharts.com/master/studies/csv-export/csv.php

    Highcharts.getOptions().exporting.buttons.contextButton.menuItems.push({
        text: 'Download CSV',
        onclick: function () {
            Highcharts.post('http://www.highcharts.com/studies/csv-export/csv.php', {
                csv: this.getCSV()
            });
        }
    });
}(Highcharts));

After some research, I found out that the real reason why this "strange" behaviour happened is located in this line of code:

var xAxis = this.options.xAxis[0];

I didn't realize that the new var xAxis is treated "like a pointer" to the real Highcharts object, so pushing/unshifting values to/from that variable would modify the original object also. This behaviour (similar to 'pass by reference') happens only with objects and this is what really misleaded me. JavaScript is really sneaky in this case.

Upvotes: 0

Views: 1063

Answers (1)

Paweł Fus
Paweł Fus

Reputation: 45079

The problem is probably that this: columns[0].unshift(""); is modifying original categories.

Solution? Use copy of categories, for example:

    if (xAxis.categories) {
        var c = $.merge([''], xAxis.categories);
        columns.push(c);
    }

If this doesn't help, recreate issue on jsFiddle, please.

Upvotes: 1

Related Questions