Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

backbone view + google visualisation api

I'm trying to integrate a google visualisation chart into my backbone.js app. Currently I have both the google.load(visualization) and setOnLoadCallback(drawVisualization) calls in the render function of a ChartView class. The google visualisation libraries seem to be loading correctly, however the callback is never executed.

Below is a example that shows the problem, if someone could assist I'd be very grateful!

<!doctype html>
<html>
<head>
    <title>App</title>
    <meta charset="utf-8">
</head>
<body>
<div id="content"></div>

<script src="lib/jquery-1.7.2.min.js"></script>
<script src="lib/underscore.js"></script>
<script src="lib/backbone.js"></script>
<script src="http://www.google.com/jsapi"></script>

<script>

    ChartView = Backbone.View.extend({

        render:function () {
            $(this.el).html('<p>gviz line chart:</p>' +
                    '<div id="gviz" style="width:600px; height:300px;"></div>');
            google.load('visualization', '1', {packages:'linechart'});
            google.setOnLoadCallback(this.drawVisualization);
            return this;
        },

        //This never gets called
        drawVisualization:function () {
            console.log("In draw visualization");
            var data = this.createDataTable('date');
            var chart = new google.visualization.LineChart(this.$('#gviz'));
            chart.draw(data, null, null);
        },

        createDataTable:function (dateType) {
            console.log("Creating datatable");
            var data = new google.visualization.DataTable();
            data.addColumn(dateType, 'Date');
            data.addColumn('number', 'Column A');
            data.addColumn('number', 'Column B');
            data.addRows(4);
            data.setCell(0, 0, new Date("2009/07/01"));
            data.setCell(0, 1, 1);
            data.setCell(0, 2, 7);
            data.setCell(1, 0, new Date("2009/07/08"));
            data.setCell(1, 1, 2);
            data.setCell(1, 2, 4);
            console.log("Created datatable " + data.toJSON());
            return data;
        }

    });

    var AppRouter = Backbone.Router.extend({
        routes:{
            "":"chart"
        },
        chart:function () {
            console.log("Showing chart");
            $("#content").append(new ChartView().render().el);

        }
    });

    router = new AppRouter();
    Backbone.history.start();

</script>

</body>
</html>
like image 961
MarkNS Avatar asked Jun 07 '12 01:06

MarkNS


2 Answers

Ok, to record this for posterity before another month goes by. It's possible to set the callback as an arg to the google.load call itself, rather than use the google.setOnLoadCallback method. Also had to tweak the code to get the first child of the jquery object and it works fine.

ChartView = Backbone.View.extend({

    render:function () {
        $(this.el).html('<p>gviz line chart:</p>' +
                '<div id="gviz" style="width:600px; height:300px;"></div>');
        google.load('visualization', '1',  {'callback':this.drawVisualization,
            'packages':['linechart']});
        return this;
    },

    drawVisualization:function () {
        console.log("In draw visualization");
        var data = new google.visualization.DataTable();
        data.addColumn('date', 'Date');
        data.addColumn('number', 'Column A');
        data.addColumn('number', 'Column B');
        data.addRows(4);
        data.setCell(0, 0, new Date("2009/07/01"));
        data.setCell(0, 1, 1);
        data.setCell(0, 2, 7);
        data.setCell(1, 0, new Date("2009/07/08"));
        data.setCell(1, 1, 2);
        data.setCell(1, 2, 4);
        var chart = new google.visualization.LineChart(this.$('#gviz').get(0));
        chart.draw(data, null, null);
    }

});
like image 88
MarkNS Avatar answered Oct 12 '22 23:10

MarkNS


If you're using require.js for dependency management, I've found that using the single-call for loading specific modules works nicely.

    define(
        [
        'backbone'
        , 'socialPages/data/statCollection'
        , 'date'
        , 'https://www.google.com/jsapi?autoload={"modules":[{"name":"visualization","version":"1","packages":["corechart","table"]}]}'
        ], function(
        Backbone
        , StatsCollection
        ) {

return Backbone.View.extend({
    initialize: function() {
        _.bindAll( this
            , '_chartDataChanged'
            , '_drawChart'
            , '_fetchStats'
            , '_generateFields'
            , '_generateRows'
            , '_generateStatsTotals'
            , '_lineChartOptions'
            , '_onItemSelected'
            , '_padWithZeroValues'
            , '_setChartDimensions'
            , 'clean'
            , 'render'
        );

        this._firstRender       = true;
        this._sampleRate        = 'month';
        this.statsCollection    = new StatsCollection();
        this.dimensions         = this._setChartDimensions();
        this.statsCollection.bind( 'all' , this._chartDataChanged );
        this._fetchStats();
        if( window.google ) {
            google.setOnLoadCallback( this._drawChart );
        }

    }
like image 24
Benjamin Dean Avatar answered Oct 13 '22 00:10

Benjamin Dean