Adding Listener to update charts on ButtonClick

1,748 views
Skip to first unread message

Tony Holmes

unread,
Nov 8, 2011, 12:35:28 PM11/8/11
to Google Visualization API
Hi,

non-coder getting to grips with Javascript.

I want to change the isStacked status of a chart on ButtonClick....
have looked at code samples on Code Playground (Dashboards and
Controls) but declaration of Dashboard is different to other code
examples (which my code is based on).

Is there an easy way to integrate a listener to my dashboard element
to update chart. I was trying the following but realised that maybe
since "stackButton" is not declared within the visualisation this will
not work??

// "listen" for button-click...
google.visualization.events.addListener('stackButton', 'onclick'
function() {
mainChart.setOption('isStacked', true);
mainChart.draw();
}

Note I don't want to force a full redraw as this will set all options
back to default.

Location of code page to view source code... http://members.upc.ie/tony.holmes/Categories.htm.

Thanks in advance for any assistance.
Regards
Tony

asgallant

unread,
Nov 8, 2011, 1:23:50 PM11/8/11
to google-visua...@googlegroups.com
Try adding a parameter to the drawCharts() function, and pass a boolean when you call it.  Use the parameter for your 'isStacked' option, then you can hook the button clicks and pass the function call with appropriate parameters, ex: http://jsfiddle.net/zggXp/

Tony Holmes

unread,
Nov 9, 2011, 5:02:07 AM11/9/11
to Google Visualization API
Hi asgallant,

Thanks for the response.

I believe I understand what you are suggesting for the function
drawCharts(isStacked)....

The option "isStacked" would have a "variable" called "isStacked"
drawCharts(isStacked) would then be called in the following manner
drawCharts(true)... Yes/No?

However the more problematic thing for me is how and where a listener
is determined in the code to "listen" for the "onClick" event, if and
when the "stackButton" is clicked. Based on available code samples on
the code playground I see the following...

// Create the dashboard
var dashboard = new google.visualization.Dashboard(
document.getElementById('dashboard'));

// Register a listener to be notified once the dashboard is ready.
google.visualization.events.addListener(dashboard, 'ready',
dashboardReady);

// Configure the dashboard so that the slider to affect the
piechart,
// then draw the dashboard.
dashboard.bind(slider, piechart).draw(data);
}

function dashboardReady() {
// The dashboard is ready to accept interaction. Configure the
buttons to
// programmatically affect the dashboard when clicked.

// Change the slider selected range when clicked.
document.getElementById('rangeButton').onclick = function() {
slider.setState({'lowValue': 2, 'highValue': 5});
slider.draw();
};

// Change the pie chart rendering options when clicked.
document.getElementById('optionsButton').onclick = function() {
piechart.setOption('is3D', true);
piechart.draw();
};
}​

google.setOnLoadCallback(drawVisualization);

However this differs from my declaration of the Dashboard (developed
from other code samples) in that I do not create a variable to to hold
the "Dashboard"

// Create a dashboard
new
google.visualization.Dashboard(document.getElementById('dashboard')).
// Establish bindings, declaring Year and Category control all charts.
bind([yearControl, categoryControl], [mainSite, emeaSite, tierSite,
compareSite]).
// bindings to control site pick... each chart can display data from
different sites.
bind([mainSiteControl], [mainSite]).
bind([emeaSiteControl], [emeaSite]).
bind([tierSiteControl], [tierSite]).
bind([compareSiteControl], [compareSite]).

// Draw the entire dashboard.
draw(data);
}


// setting the value and calling the drawing function
function setValue(thisValue) {
x = eval(thisValue); // assigning the real array (as passed by the
dropdown)
drawCharts(); // calling the drawing function
}

google.setOnLoadCallback(drawVisualization);

My understanding is that I need an event listener, but how do I
implement within my code.

Tony Holmes

unread,
Nov 9, 2011, 9:19:19 AM11/9/11
to Google Visualization API
Doing a lot of reading on the web and getting nowhere. Latest attempt
was to do the following but to no avail...


// function to add an event listener to button id="stackButton"
// function loaded in <body onload="load();">
function load() {
var changeChart = document.getElementById('stackButton');
changeChart.addEventListener('click',updateChart,false );
}


// function to change the change the option "isStacked" on the chart
to "true"
function updateChart() {
mainChart.setOption('isStacked', true);
mainChart.draw();
}

also tried calling drawCharts(); which works elsewhere in my code.

Any help much appreciated.

Thanks

asgallant

unread,
Nov 9, 2011, 9:38:00 AM11/9/11
to google-visua...@googlegroups.com
You need an event listener, but you don't use the Google viz API listeners for non-chart elements.  Standard javascript event listeners work fine.  Try putting one of these in the function you call from google.setOnLoadCallback (don't recall what it is) or in a document.ready event listener function:

// option 1
// store the stacked value, then add the event listeners
var stacked false;
document.getElementById('stackButton').onClick function ({
    if (!stacked{
        drawCharts(true);
    }
};
document.getElementById('unStackButton').onClick function ({
    if (stacked{
        drawCharts(false);
    }
};

// option 2
// use 1 button, store stacked value in button and toggle stacked
// status and button text on click
document.getElementById('stackUnstack').onClick function ({
    var stacked !(eval(this.value));
    drawCharts(stacked);
    if (stacked{
        this.innerHTML 'Stack';
    }
    else {
        this.innerHTML 'Unstack';
    }
    this.value stacked;
};

asgallant

unread,
Nov 9, 2011, 9:51:15 AM11/9/11
to google-visua...@googlegroups.com
Ignore my last post.

You might be having a scope issue here.  I fixed up the event listeners from my last post and initialize them on the dashboard's 'ready' event, which should avoid scope issues: http://jsfiddle.net/zggXp/1/

You can easily adjust for the single-button toggle option I presented as well.

Tony Holmes

unread,
Nov 9, 2011, 1:20:12 PM11/9/11
to Google Visualization API
Not sure if I got everything from your last posts... tried a few
variations but no joy, then found the following...

LOADING EVENT LISTENERS
One of the issues with event listeners and the DOM is that in order
for them to work properly the elements have to be already declared.
Otherwise, there is nothing for either of them to work with. The
solution lies within the load event of the window.

To bypass this dilemma, you create an extra function that will load
your needed event listeners, which will be triggered by the window's
loading event:

Tested this out with the following.....


function buttonClicked() {
alert("Button was clicked!");
}

function addListeners() {
var iampressed = document.getElementById("stackButton");
iampressed.addEventListener('click', buttonClicked, false);
}

window.addEventListener('load', addListeners, false);

This worked in that when I clicked the stackButton, I get the alert
"Button was clicked". So the click event "is" being passed to
function buttonClicked().

However when I change the buttonClicked function to the following...


function buttonClicked() {
mainSite.setOption('isStacked', true);
drawCharts();
}

.... I don't get a chart redraw reflecting the suspected change?

Any ideas. I have uploaded the full page to http://members.upc.ie/tony.holmes/Categories.htm
for review.

To see the charts in operation choose a multiple month option (Q1, Q2,
H1... etc). This will show monthly usage... by stacking the chart I
should see usage for the year so far!

Thanks again for all your assistance.

asgallant

unread,
Nov 9, 2011, 1:42:49 PM11/9/11
to google-visua...@googlegroups.com
The problem is that the mainSite variable is not in scope for your event listener.  Register your button click listeners in the dashboard's 'ready' event listener (as I did above) - this will put the variable in scope of the event listener.  The dashboard will fire it's 'ready' event after the rest of the DOM, so you don't have to worry about your buttons not existing yet.  Furthermore, the buttons 'click' event listener won't be registered until the dashboard is drawn, so you don't end up accidentally trying to redraw the charts before they finish drawing the first time.

Tony Holmes

unread,
Nov 9, 2011, 6:08:07 PM11/9/11
to Google Visualization API
Eventually figured the notation on the Dashboard and added the
Listener as you described and "Stacked" & "UnStacked" buttons now
work.

There is another problem now however, that I have noticed... the
DrawCharts() function initialises all controls on each call. This is
a problem where the potential End User has used the category pickers
for Year and the various Sites to see the sites they want to
compare. Once they click either of the buttons to stack or unstack
the charts, the charts are redrawn with the category pickers default
values.

Looking at the code playground there is an example of Programmatic
Control Changes, where a pie chart is drawn independently, rather than
call drawVisualization(). I understand that this may be a scope
issue again but I am not seeing a solution.

page @ http://members.upc.ie/tony.holmes/Categories.htm

Thanks
Tony

asgallant

unread,
Nov 10, 2011, 9:13:16 AM11/10/11
to google-visua...@googlegroups.com
Use the new version of the event handlers I wrote above (http://jsfiddle.net/zggXp/2/), which redraws only the mainSite chart:

// create a variable to hold stacked status and add listeners to redraw the chart
var stacked false;
google.visualization.events.addListener(dashboard'ready'function ({

    document.getElementById('stackButton').onClick function ({
        if (!stacked{
            mainSite.setOption('isStacked'true);
            mainChart.draw();
            stacked !stacked;

        }
    };
    document.getElementById('unStackButton').onClick function ({
        if (stacked{
            mainSite.setOption('isStacked'false);
            mainChart.draw();
            stacked !stacked;
        }
    };
});

You can also remove the parameter you pass to the drawCharts() function, as it is no longer needed.

Tony Holmes

unread,
Nov 10, 2011, 1:11:08 PM11/10/11
to Google Visualization API
Have posted the latest version to... http://members.upc.ie/tony.holmes/Categories-rev1.htm

Still no joy!
I think the problem may be the reference to mainSiteChart is not
correct... when I set the initial value for "stacked" = "true", this
was not represented when the dashboard loads and I choose [say] "H1"
as the reference period.

if I put "stacked" as Global variable... the charts are stacked.

However I think problem may be with the "Listener" . I set global
stacked variable to "false" then tried the following...

google.visualization.events.addListener(dashboard, 'ready', function
() {
document.getElementById('stackButton').onClick = function () {
if (stacked == false) {
alert("Stacked variable is false");
}
};

});

no alert box was returned. it would appear the button onclick event
is not "heard" by the listener. Is this assumption correct??

Tony Holmes

unread,
Nov 10, 2011, 1:58:37 PM11/10/11
to Google Visualization API
Small tweak based on code on Code Playground and event listener is now
registering the button click events... used drawVisualization(); to
test redraw of charts and it works except for the problem of drawing
the complete dashboard (with all default values!!!).

http://members.upc.ie/tony.holmes/Categories-rev2.htm

The problem then is how to correctly call mainSiteChart.draw();



On Nov 10, 6:11 pm, Tony Holmes <mail.tonyhol...@gmail.com> wrote:
> Have posted the latest version to...http://members.upc.ie/tony.holmes/Categories-rev1.htm

asgallant

unread,
Nov 10, 2011, 2:56:58 PM11/10/11
to google-visua...@googlegroups.com
This line:

google.visualization.events.addListener(dashboard, 'ready', dashboardReady);

is your problem.  The chart variables you need are not in scope for the dashboardReady function, which is why it doesn't work.  Use the method I posted above which passes the function in scope.

Tony Holmes

unread,
Nov 10, 2011, 5:59:43 PM11/10/11
to Google Visualization API
To be honest I not sure how this works because my brain is melting
just thinking about scope!

I have uploaded the code page to http://members.upc.ie/tony.holmes/Categories.htm
for you to have a look at if you're interested.

Please accept my sincere thanks for your patience and assistance

Best Regards
Tony

asgallant

unread,
Nov 11, 2011, 9:53:41 AM11/11/11
to google-visua...@googlegroups.com
Scope can be a pain, especially if you're new to programming.  Basically, variables declared inside a function don't exist outside of that function, so when you set up your charts, the dashboardReady() function couldn't access the variables that hold the charts.  By moving that function inside the chart drawing function, it can access all the variables it needs.  I replicated your site on jsfiddle, so you can see it working: http://jsfiddle.net/92HQu/

Replace the contents of your <script> tags with that javascript and you should be all set.
Reply all
Reply to author
Forward
0 new messages