Shalom Slavin
Shalom Slavin

Reputation: 93

Google Visualization API Called Multiple Times Permission Denied (IE)

I am new to the Google Charts API and am trying to implement it on one of our pages.

What I have is a datatable which is filtered clientside. I want to redraw my charts client side as well, in real time. After some issues I've discovered (on SO) that if you call google.load AFTER the page loads (i.e. by having some button onclick), it wipes out your html, and the solution there seems to be google.load('version','package',{callback:.....}) to force it to append rather than inject. The problem there is that now the callback needs to be a global function, otherwise it won't resolve to anything in that inner context (or so it seemed)..

Due to the above, my current setup is as follows:
1) The script at https://www.google.com/jsapi is included
2) google.load is called, passing in a callback pointer to my function which has the drawing logic

Now #2 is the weird part, in the examples I've seen, "alert(zzz)" was passed in as a demo callback, for me I want to, obviously, draw the charts. But the charts all have different data so therefore the function is different each time it's called.

As a test, I defined a global variable called "CALLBACK_PTR", and I then point that to an anonymous function which is re-defined with the new data every time the user clicks a button.

This works, the data is properly displayed and updated, BUT if I look at dev tools in IE on button clicks (i.e. function calls) #2+, I see a bunch of permission denied errors. Any clue as to what that is?

JS code below:

var CALLBACK_PTR;

function createChart(sChartType,sContainerID,oData,oOptions)
{
CALLBACK_PTR = null;

// Load the Visualization API and the piechart package.
google.load('visualization', '1.0',{'callback':'CALLBACK_PTR()'});      


// Set a callback to run when the Google Visualization API is loaded.
//google.setOnLoadCallback(drawVisualization);


CALLBACK_PTR = function () {

    var oDataTable = new google.visualization.arrayToDataTable(
        oData
    );

    var wrapper = new google.visualization.ChartWrapper(
        {
            chartType: sChartType,
            dataTable: oDataTable,
            options:oOptions,
            containerId:sContainerID
        }
    );

    wrapper.draw();


    //interactivity, will build on this in the future
    google.visualization.events.addListener(wrapper,'ready',function(){
        var chart=wrapper.getChart();
        google.visualization.events.addListener(chart, 'select',function(){         
                        var selectedItem = chart.getSelection()[0];
                        if (selectedItem) {
                            var value = oDataTable.getValue(selectedItem.row, selectedItem.column);
                            alert('Value:' + value);
                        }
                    })//end inner anon function         
    });

    } // end draw function

}//end createChart

This is all a bit weird but it does work, except for the permission denied thing. This is called from the client page via createChart(...) whenever they click a button (that filters the visible data).

The error you would see in a JS debugger:

SCRIPT70: Permission denied 
format+en,default+en.I.js, line 83 character 16

Clicking it takes me to Googles obfuscated code:

if(1==a[ed])

And if I hover over "a" all the attributes (id,name,etc) say permission denied under the "value".

Any input would be appreciated.

P.S. Doesn't it make sense to call google.load AFTER you define your callback function? Whether you use callback:{} or setOnLoadCallback, why wouldn't you first define the callback? Especially in my case where it changes.

Feel free to critique the interactivity code I had to write due to using a wrapper, since wrapper.getChart doesn't work until wrapper is ready, I had to wrap my chart listener in the wrapper 'ready' listener.

EDIT

I tried simplifying it to:

function createChart(sChartType,sContainerID,oData,oOptions)
{
if(CHART){
    //clear the old chart --TODO:, what if they want to generate multiple charts??
    CHART.clearChart();
}

CALLBACK_PTR = null;
CALLBACK_PTR = function () {

    var oDataTable = new google.visualization.arrayToDataTable(
        oData
    );

    CHART = new google.visualization.LineChart(document.getElementById(sContainerID)).
      draw(oDataTable, oOptions);

    } // end draw function


    // Load the Visualization API and the piechart package.
    google.load('visualization', '1.0',{'packages':['corechart'],'callback':'CALLBACK_PTR()'});
}//end function createChart

But still no luck..still get permission denied even with the clearing the chart references some others suggested in other posts.

ANOTHER EDIT The code above is bad, the line:

CHART = new google.visualization.LineChart(document.getElementById(sContainerID)).
  draw(oDataTable, oOptions);

Should be:

CHART = new google.visualization.LineChart(document.getElementById(sContainerID));
    CHART.draw(oDataTable, oOptions);

Otherwise "CHART" was whatever .draw returned, meaning my .clearChart wasn't working.

So now that that works, is there a "clearWrapper" equivalent? Because my original code used a wrapper so that callers can pass in a chart type and not need to worry about maintaining different objects..

Upvotes: 0

Views: 628

Answers (1)

Shalom Slavin
Shalom Slavin

Reputation: 93

Ok so here's what was going on.

CHART.clearChart() does fix the issue - I confirmed this. The problem was I wasn't setting my CHART reference properly because in my first example I defined the wrapper ready event AFTER calling .draw, which was too late, you need to define the ready event listener before calling draw.

Once I fixed that, and clearChart was being properly called, the errors stopped.

Upvotes: 1

Related Questions