1
votes

I'm new in Google Chart API. I want to use it to visualize my data about the review on Google Play Store which include multiple issues, sentiments and other conditions.

I want to build a horizontal bar chart which x axis containing different app , and each app's containing 7 issues, y axis is the sum of sentiment of each issue in different app.

I have already done the horizontal chart containing all data in a single div element. However, for the user's convenience, I want to show 5 data at most in a single div element, and dynamically create div element if there is more than 5 data in the current data set. At last, the div elements which paint the chart will horizontally append to the another div element called issueBar_div. The user can use the scrollbar to view different chart.

What I've done:

  1. Partition data:

    var title = ['APP'];
    var issueRow = {{ projectissues|safe }}; // 7 different issues got from Django
    var graph_data = [title.concat(issueRow)];
    var cnt = 0;
    var divide_row = [];
    var tableRows = ... // tableRows is the app name mapping to sentiment sum which corresponding to different issue array dictionary.
    // like the form  APP -> [20, 12, -1, 3, 5, 21, 57]
    for (var app in tableRows) {
            cnt ++;                                
            var row = [app];
            for (var i = 0; i < tableRows[app].length; i++) {
                row.push(tableRows[app][i]);
            }
            if(cnt < 6){
                divide_row.push(row);
            }
            else{
                graph_data.push(divide_row);
                divide_row = [];
                cnt = 0;
            }
    }
    
  2. Create the div element and draw the chart

In order to build a use the scrollbar, I add some restriction to the issueBar_div.

<div id="issueBar_div" style="height:400px; overflow-x:scroll; overflow-y:hidden";></div>

Dynamically create the div element and draw.

    function drawIssueBar() {
        var issueBar = document.getElementById("issueBar_div");
        // titleRow include the APP and other issue
        var titleRow = graph_data[0];
        delete_element();
        for(var i = 1;i<graph_data.length;i++){
            // create div element and set their attribute
            var my_div = document.createElement("div");
            my_div.id = "issuebar_" + i;
            my_div.style.display = "table-cell";
            // append this element to #issueBar_div
            issueBar.appendChild(my_div);
            // get the sliced data and push to total_data
            var row_data = graph_data[i];
            var total_data = [titleRow];
            for(var k=0;k<row_data.length;k++){
                total_data.push(row_data[k]);
            }
            // the new data container
            var data = new google.visualization.arrayToDataTable(total_data);
            var div_width = $("#home").width();
            var materialOptions = {
                height: 400,
                width: div_width,
                hAxis: {
                    title: 'Sum of sentiment'
                },
                vAxis: {
                    title: 'APP'
                },
                bars: 'vertical'
            };
            var materialChart = new google.charts.Bar(document.getElementById("issuebar_" + i));
            materialChart.draw(data, materialOptions);
        } 
    }
    // delete the div element
    function delete_element(){
        i = 1;
        while(true){
            element = document.getElementById("issuebar_" + i);
            if(element !== null){
                element.outerHTML = "";
                delete element;
                i++;
            }
            else{
                break;
            }
        }
    }

Current Problem:

Basically, the created div elements will create as expect, but the chart will only show one chart as below.

The successful chart

The fail part when move the scrollbar to right

How can I solve this problem?

Any answer will be greatly appreciated. Thanks.

1
Hi @WhiteHat, I have already tried it. It's a pity that the result remain the same. - 黃晨懿
No, there are just unrelated warning there. - 黃晨懿
what is the value of --> graph_data[0] -- does this return an array or single value? - WhiteHat
it return a array, like the form of ["APP", "issue1", "issue2", "issue3"... "issue7"]. It will be the column name of each bar in bar chart. - 黃晨懿

1 Answers

0
votes

ALL. I have already solve my problem!!!

I notice that there is a very important sentence showing on Google Chart document:

For each chart on the page, add a call to google.charts.setOnLoadCallback() with the callback that draws the chart as an input

So I decide to callback drawing method when drawing each bar chart.

The specific solution

1.I use the new Function as a callback function. The row_data is the data needing to present, and the my_div is the div element where to store the chart.

var drawIssueBar = new Function("row_data", "my_div",
        "var data = google.visualization.arrayToDataTable(row_data);" +
        "var div_width = $('#home').width();" +
        "var materialOptions = {" + 
            "height: 400," + 
            "width: div_width," + 
            "hAxis: {" +
                "title: 'Sum of sentiment'" +
            "}," +
            "vAxis: {" +
                "title: 'APP'" +
            "}," +
            "bars: 'vertical'" +
        "};"+
        "var materialChart = new google.charts.Bar(my_div);" +
        "materialChart.draw(data, materialOptions);"
    );

2.Rewrite the data processing.

    var titleRow = ... // like the form of ["APP", "issue1", "issue2", ..."issue7"]
    var cnt = 0;
    var divide_row = [];

    for (var app in tableRows) {
        cnt ++;                                
        var row = [app].concat(tableRows[app]);
        if(cnt < 6){
            divide_row.push(row);
        }
        else{
            graph_data.push([titleRow].concat(divide_row));
            // console.log(graph_data[graph_data.length - 1]);
            divide_row = [];
            cnt = 0;
        }
    }

3.Write a new function called drawIssueChart to draw all the bar chart.

    function drawIssueChart(){
        // create the div element and draw the chart
        delete_element();
        var issueBar = document.getElementById('issueBar_div');
        for(var i = 0;i<graph_data.length;i++){
            var my_div = document.createElement("div");
            my_div.id = "issuebar_" + i;
            my_div.style.display = "table-cell";
            issueBar.appendChild(my_div);
            var row_data = graph_data[i];
            // use the drawIssueBar as a callback
            google.charts.setOnLoadCallback(drawIssueBar(row_data, my_div));
        }
    }

Result

The successful chart

Another successful chart when moving the scrollbar to right

I learn a lot from this solution!

Hopefully it can help the people who encounter this problem.